【中等】【337】打家劫舍III【树形DP】


链接点我

题目描述

在这里插入图片描述

思路

1.暴力递归-最优子结构

在这里插入图片描述

    public int rob(TreeNode root) {
        if(root == null){
            return 0;
        }
        int money = root.val;
        if(root.left != null){
            money += rob(root.left.left) + rob(root.left.right);
        }
        if(root.right != null){
            money += rob(root.right.left) + rob(root.right.right);
        }
        return Math.max(money,rob(root.left)+rob(root.right));
    }

在这里插入图片描述

2. 记忆化-解决重复子问题

针对解法一种速度太慢的问题,经过分析其实现,我们发现爷爷在计算自己能偷多少钱的时候,同时计算了4个孙子能偷多少钱,也计算了2个儿子能偷多少钱。这样在儿子当爷爷时,就会产生重复计算一遍孙子节点。

于是乎我们发现了一个动态规划的关键优化点
重复子问题
我们这一步针对重复子问题进行优化,我们在做斐波那契数列时,使用的优化方案是记忆化,但是之前的问题都是使用数组解决的,把每次计算的结果都存起来,下次如果再来计算,就从缓存中取,不再计算了,这样就保证每个数字只计算一次。
由于二叉树不适合拿数组当缓存,我们这次使用哈希表来存储结果,TreeNode当做key,能偷的钱当做value

    public int rob(TreeNode root) {
        if(root == null){
            return 0;
        }
        HashMap<TreeNode,Integer> memo = new HashMap<>();
        return robCore(root,memo);
    }
    
    private int robCore(TreeNode root,HashMap<TreeNode,Integer> memo){
        if(root == null){return 0;}
        if(memo.containsKey(root)){
            return memo.get(root);
        }
        int money = root.val;
        if(root.left != null){
            money += robCore(root.left.left,memo)+robCore(root.left.right,memo);
        }
        if(root.right != null){
            money += robCore(root.right.left,memo)+robCore(root.right.right,memo);
        }
        int result = Math.max(money,robCore(root.left,memo)+robCore(root.right,memo));
        memo.put(root,result);
        return result;
    }

在这里插入图片描述

3.终极解法

在这里插入图片描述

    public int rob(TreeNode root) {
        if(root == null){
            return 0;
        }
        int[] result = robCore(root);
        return Math.max(result[0],result[1]);
    }
    
    public int[] robCore(TreeNode root){
        if(root == null){
            return new int[2];
        }
        int[] result = new int[2];
        
        int[] left = robCore(root.left);
        int[] right = robCore(root.right);
        
        result[0] = Math.max(left[0],left[1])+ Math.max(right[0],right[1]);
        result[1] =left[0] + right[0] + root.val;
        
        return result;
    }
发布了55 篇原创文章 · 获赞 1 · 访问量 868

猜你喜欢

转载自blog.csdn.net/weixin_42469108/article/details/105074425