每日一题 337. 打家劫舍 III

发布于:2024-12-22 ⋅ 阅读:(13) ⋅ 点赞:(0)

337. 打家劫舍 III

背包问题的变形


class Solution {
public:
    int rob(TreeNode* root) {
        unordered_map<TreeNode*,int> mpYes;
        unordered_map<TreeNode*,int> mpNo;

        int ans = 0;
         dfs(root,mpYes,mpNo);
        return max(mpNo[root],mpYes[root]);
    }

    void dfs(TreeNode* root,unordered_map<TreeNode*,int> &mpYes, unordered_map<TreeNode*,int> &mpNo )
    {
        if(!root)
        {
            mpYes[root] = 0;
            mpNo[root]  = 0;
            return;
        }
        if(!root->left && !root->right)
        {
            mpYes[root] = root->val;
            mpNo[root]  = 0;
            return ; 
        }
        if(!mpYes.count(root->left)){
            dfs(root->left,mpYes,mpNo);
        } 
        if(!mpYes.count(root->right))
        {
            dfs(root->right,mpYes,mpNo);
        }
        
        int yesVal = root->val;
        int noVal  = 0;
        yesVal += mpNo[root->left] + mpNo[root->right];
        noVal  += (max(mpNo[root->left]+mpNo[root->right],mpYes[root->left]+mpYes[root->right]));
        noVal = max(noVal,mpNo[root->left]+mpYes[root->right]);
        noVal = max(noVal,mpNo[root->right]+mpYes[root->left]);
        mpYes[root] = yesVal;
        mpNo[root]  = noVal;
        //cout<<root->val<<" "<<yesVal<<" "<<noVal<<endl;

    }
};

更高效的算法

int rob(TreeNode* root) {
        pair<int, int> result = dfs(root);
        return max(result.first, result.second);
    }

private:
    // 返回值为 pair<int, int>,分别表示 (不偷该节点的最大值, 偷该节点的最大值)
    pair<int, int> dfs(TreeNode* root) {
        if (!root) return {0, 0};

        // 后序遍历:先计算左右子树
        pair<int, int> left = dfs(root->left);
        pair<int, int> right = dfs(root->right);

        // 不偷当前节点
        int notRob = max(left.first, left.second) + max(right.first, right.second);
        // 偷当前节点
        int rob = root->val + left.first + right.first;

        return {notRob, rob};
    }