337. 打家劫舍 III Krains 2020-08-05 10:18:45 动态规划

时间:2022-07-22
本文章向大家介绍337. 打家劫舍 III Krains 2020-08-05 10:18:45 动态规划,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

# 题目链接

# 记忆化递归

解题思路

  • 对于一个结点,可偷可不偷,用dfs搜索所有可能方案,返回一个最大值
  • 对于一个结点,对该结点以及其子树行窃所能偷的最大值是确定的,因此可以使用记忆化,以当前结点为key记录当前结点所能行窃的最大值
class Solution {
    Map<TreeNode, Integer> memo = new HashMap<>();

    public int rob(TreeNode root) {
        return helper(root);
    }

    public int helper(TreeNode root){
        if(root == null)
            return 0;
        if(memo.containsKey(root))
            return memo.get(root);

        // t1代表对当前root行窃,行窃后就不能够对其相邻的左右孩子动手
        // 因此,直接跳过其左右孩子
        int t1 = root.val;
        if(root.left != null)
            t1 += helper(root.left.left) + helper(root.left.right);
        if(root.right != null)
            t1 += helper(root.right.left) + helper(root.right.right);
		
        // t2表示不对当前root行窃
        int t2 = 0;
        t2 += helper(root.left) + helper(root.right);
        
        // 取最大值,并记忆
        t1 = Math.max(t1, t2);
        memo.put(root, t1);
        return t1;
    }
}

# 动态规划

解题思路

  • 用一个数组a记录状态,a[0]表示对当前root行窃的最大值,a[1]不对当前root行窃的最大值
  • 假设root左右结点返回的状态分别为left,right,那么
    • a[0]=root.val+left[1]+right[1],对root行窃,那么对其相邻的左右孩子只能不行窃
    • a[1]=max(left[0],left[1])+max(right[0],right[1]),对root不行窃,对其左右孩子可偷可不偷,选择偷或不偷的最大值
class Solution {
    public int rob(TreeNode root) {
        int[] ans = helper(root);
        return Math.max(ans[0], ans[1]);
    }

    public int[] helper(TreeNode root){
        if(root == null)
            return new int[]{0, 0};
        
        int[] left = helper(root.left);
        int[] right = helper(root.right);

        return new int[]{root.val + left[1] + right[1], 
                      Math.max(left[0], left[1]) + Math.max(right[0], right[1])};
    }
}