打家劫舍(三)

LeetCode算法网站算法题

https://leetcode-cn.com/problems/house-robber-iii/

用 f(o) 表示选择 o 节点的情况下,o 节点的子树上被选择的节点的最大权值和;g(o) 表示不选择 o 节点的情况下,o 节点的子树上被选择的节点的最大权值和;l 和 r 代表 o 的左右孩子。

(1)当 o 被选中时,o 的左右孩子都不能被选中,故 o 被选中情况下子树上被选中点的最大权值和为 l 和 r 不被选中的最大权值和相加,即 f(o)=g(l)+g(r)
(2)当 o 不被选中时,o 的左右孩子可以被选中,也可以不被选中。对于 o 的某个具体的孩子 x,它对 o 的贡献是 x 被选中和不被选中情况下权值和的较大值。即g(o)=max{f(l),g(l)}+max{f(r),g(r)}

Java递归解法——后序遍历的原因是我们需要知道当前节点子孩子的最大权值才能做判断

class Solution {
    HashMap<TreeNode,Integer>choose=new HashMap<TreeNode,Integer>();
    HashMap<TreeNode,Integer>no_choose=new HashMap<TreeNode,Integer>();
    public int rob(TreeNode root) {
        dfs(root);
        return Math.max(choose.getOrDefault(root,0),no_choose.getOrDefault(root,0));
    }
    void dfs(TreeNode root){
        if (root==null){
            return;
        }
        dfs(root.left);
        dfs(root.right);
        choose.put(root,root.val+no_choose.getOrDefault(root.left,0)+no_choose.getOrDefault(root.right,0));
        no_choose.put(root,Math.max(choose.getOrDefault(root.left,0),no_choose.getOrDefault(root.left,0))+Math.max(choose.getOrDefault(root.right,0),no_choose.getOrDefault(root.right,0)));
    }
}

C++优化代码——还没看

struct SubtreeStatus {
    int selected;
    int notSelected;
};

class Solution {
public:
    SubtreeStatus dfs(TreeNode* o) {
        if (!o) {
            return {0, 0};
        }
        auto l = dfs(o->left);
        auto r = dfs(o->right);
        int selected = o->val + l.notSelected + r.notSelected;
        int notSelected = max(l.selected, l.notSelected) + max(r.selected, r.notSelected);
        return {selected, notSelected};
    }

    int rob(TreeNode* o) {
        auto rootStatus = dfs(o);
        return max(rootStatus.selected, rootStatus.notSelected);
    }
};

 

 

©️2020 CSDN 皮肤主题: 1024 设计师:上身试试 返回首页