leetcode题解:打家劫舍(三)

2022/05/05 leetcode 算法 共 2572 字,约 8 分钟

题目链接

非常感谢的评论

这题看上去不是很难,我按照我的理解,用动态规划的思想,写下了如下的代码:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
private:
    unordered_map<TreeNode*, int> memo;
public:
    int money(TreeNode* root){
        if(root==nullptr)
            return 0;
        if(memo.find(root)!=memo.end())
            return memo[root];
        int coins=0;
        if(root->left==nullptr&&root->right==nullptr)
            coins=root->val;
        else if(root->left==nullptr)
            coins=root->val+money(root->right->left)
            +money(root->right->right);
        else if(root->right==nullptr)
            coins=root->val+money(root->left->left)
            +money(root->left->right);
        else
            coins=root->val+money(root->left->left)
            +money(root->left->right)+money(root->right->left)
            +money(root->right->right);
        memo[root]=coins;
        return coins;
    }
    int rob(TreeNode* root) {
        return max(money(root),money(root->left)+money(root->right));
    }
};

我将money(root)定义为一定偷root钱的情况下达到的最大偷盗金额,用memo记录数值防止重复计算。对于某一个结点, 按照它的子结点是否存在进行分类讨论,当左右结点都存在的时候它的最大值应该是它本身加上隔层的所有结点最大值。当我提交后, 我才意识到我的做法根本不对,我的报错例子如下:

image-20220505131212496

我的代码结果是6,实际结果应该是7,过了很久我都没有意识到6的错误在哪,直到我发现4+3=7。也就是说最大值不一定是money(root)+money(root->left->left)+money(root->left->right)+money(root->right->left)+money(root->right->right)。我们没办法确定隔层的结点全部偷是最好的做法,所以这样定dp是行不通的。

我们再更改dp的定义,定义表示最大偷盗金额,但不一定会偷root本身,基本只需要改一行代码:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
private:
    unordered_map<TreeNode*, int> memo;
public:
    int money(TreeNode* root){
        if(root==nullptr)
            return 0;
        if(memo.find(root)!=memo.end())
            return memo[root];
        int coins=0;
        if(root->left==nullptr&&root->right==nullptr)
            coins=root->val;
        else if(root->left==nullptr)
            coins=root->val+money(root->right->left)
            +money(root->right->right);
        else if(root->right==nullptr)
            coins=root->val+money(root->left->left)
            +money(root->left->right);
        else
            coins=root->val+money(root->left->left)
            +money(root->left->right)+money(root->right->left)
            +money(root->right->right);
        //memo[root]=coins;
        memo[root]=max(coins,money(root->left)+money(root->right));
        return memo[root];
    }
    int rob(TreeNode* root) {
        return max(money(root),money(root->left)+money(root->right));
    }
};

文档信息

Search

    Table of Contents