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

2020-08-06 21:00:15 浏览数 (1)

# 题目链接

# 记忆化递归

解题思路

  • 对于一个结点,可偷可不偷,用dfs搜索所有可能方案,返回一个最大值
  • 对于一个结点,对该结点以及其子树行窃所能偷的最大值是确定的,因此可以使用记忆化,以当前结点为key记录当前结点所能行窃的最大值
代码语言:javascript复制
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不行窃,对其左右孩子可偷可不偷,选择偷或不偷的最大值
代码语言:javascript复制
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])};
    }
}

0 人点赞