【Leetcode】DP | 打家劫舍,当一个机灵的小偷

198 打家劫舍

D [ i ] D[i] D[i]表示前 i i i间房子的最大收益:
D [ i ] = max ⁡ ( D [ i − 1 ] , D [ i − 2 ] + n u m s [ i ] ) D [ 0 ] = n u m s [ 0 ] D [ 1 ] = max ⁡ ( n u m s [ 0 ] , n u m s [ 1 ] ) D[i] = \max(D[i -1], D[i-2]+nums[i]) \\ D[0] = nums[0] \\ D[1] = \max(nums[0], nums[1]) D[i]=max(D[i1],D[i2]+nums[i])D[0]=nums[0]D[1]=max(nums[0],nums[1])

213 打家劫舍Ⅱ

围成一圈,能偷盗的最高金额。

  • 情况1:不偷0、偷n-1
  • 情况2:不偷n-1、偷0
  • 情况3:既不偷0,也不偷n-1

【Leetcode】DP | 打家劫舍,当一个机灵的小偷_第1张图片

如何保证第一间房屋和最后一间房屋不同时偷窃呢?如果偷窃了第一间房屋,则不能偷窃最后一间房屋,因此偷窃房屋的范围是第一间房屋到最后第二间房屋;如果偷窃了最后一间房屋,则不能偷窃第一间房屋,因此偷窃房屋的范围是第二间房屋到最后一间房屋。

即取下面二者中的较大值。显然这两个式子在情况3是有重复的,但无所谓,只要覆盖了情况3就好,就可以求出最大值。
rob ( n u m s [ 0 , n − 2 ] ) ⇒  case2 + case3 rob ( n u m s [ 1 , n − 1 ] ) ⇒  case1 + case3 \text{rob}(nums[0,n-2])\Rightarrow \text{ case2 + case3} \\ \text{rob}(nums[1,n-1])\Rightarrow \text{ case1 + case3} rob(nums[0,n2]) case2 + case3rob(nums[1,n1]) case1 + case3

class Solution {
    public int rob(int[] nums, int l, int r) {
        // 偷盗nums[l,r]范围
        if (l > r) {
            return 0;
        }
        if (l == r) {
            return nums[l];
        }
        int[] D = new int[r - l + 1];
        D[0] = nums[l];
        D[1] = Math.max(nums[l], nums[l + 1]);

        for (int i = 2; i < r - l + 1; i++) {
            D[i] = Math.max(D[i - 1], D[i - 2] + nums[l + i]);
        }

        return D[r - l];
    }

    public int rob(int[] nums) {
        if (nums.length == 1) {
            return nums[0];
        }
        int res1 = rob(nums, 0, nums.length - 2);
        int res2 = rob(nums, 1, nums.length - 1);
        return Math.max(res1, res2);
    }
}

337 打家劫舍Ⅲ★

树,能偷盗的最高金额。

int rob(TreeNode root):

【一个节点具有两个属性值:(1)抢劫该节点能够得到的最大收益、(2)不抢劫该节点能得到的最大收益】

  1. 抢劫该节点,则不能抢劫两个孩子节点
  2. 不抢劫该节点,可以抢劫两个孩子节点,也可以不抢劫两个孩子节点,取其中更大的

class Solution {
    public int rob(TreeNode root) {
        int[] money = robOrNot(root);
        return Math.max(money[0], money[1]);
    }

    public int[] robOrNot(TreeNode root) {
        if (root == null) {
            return new int[]{0, 0};
        }

        int[] money = new int[2];
        int[] left = robOrNot(root.left);
        int[] right = robOrNot(root.right);

        // 不抢劫该节点
        money[0] = Math.max(left[0], left[1]) + Math.max(right[0], right[1]);
        // 抢劫该节点
        money[1] = left[0] + right[0] + root.val;

        return money;
    }
}

你可能感兴趣的:(Leetcode题解总结,leetcode,算法,数据结构)