代码随想录算法训练营 day 48: ● 198.打家劫舍 ● 213.打家劫舍II ● 337.打家劫舍III

51 阅读2分钟

198. House Robber

抢了i元素就不能抢i-1和i+1,属于比较好想的动规。dp[i]存放[0,i]子数组的最大抢劫金额,递推公式为 dp[i] = max(dp[i-1], dp[i-2] + nums[i])。取抢或不抢当前节点的最大值。

class Solution {
    public int rob(int[] nums) {

        if(nums.length == 1) {
            return nums[0];
        }

        if(nums.length == 2) {
            return Math.max(nums[0], nums[1]);
        }
        
        int[] dp = new int[nums.length];

        dp[0] = nums[0];
        dp[1] = Math.max(nums[0], nums[1]);
 
        for(int i=2; i<nums.length; i++) {
            dp[i] = Math.max(dp[i-1], dp[i-2] + nums[i]);
        }

        return dp[nums.length - 1];
    }
}

213. House Robber II

环的情况没总结好。可以只取前i-1个节点,无环,再取后i-1个节点,也无环。等于跑两次打家劫舍1,取最大值。 还有一种情形是既不取头也不取尾,那么被前两种情况覆盖。

class Solution {
    public int rob(int[] nums) {
        int[] dp = new int[nums.length - 1];

        int len = nums.length;

        if(len == 1) {
            return nums[0];
        }
        if(len == 2) {
            return Math.max(nums[0], nums[1]);
        }
        if(len == 3) {
            return Math.max(nums[0], Math.max(nums[1], nums[2]));
        }

        dp[0] = nums[0];
        dp[1] = Math.max(nums[0], nums[1]);

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

        int m1 = dp[dp.length - 1];

        for(int i=0; i<dp.length; i++) {
            dp[i] = 0;
        }

        dp[0] = nums[1];
        dp[1] = Math.max(nums[1], nums[2]);

        for(int i=3; i<len; i++) {
            dp[i-1] = Math.max(dp[i-2], dp[i-3] + nums[i]); 
        }

        int m2 = dp[dp.length - 1];

        return Math.max(m1, m2);
    }
}

337. House Robber III 在树上做动规,以前没做过。属于想不出的思路。dp数组只有两个元素,一个偷一个不偷,存放最大钱数。配合递归,在每层上都等于保留当前节点偷与不偷的最大钱数。 递推公式为:要么取当前节点,则左右子节点都不能取。 要么不取当前节点,则可以取左右子节点。 递归函数返回当前节点的dp数组。

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public int[] robDp(TreeNode root) {
        int[] res = new int[2];

        if(root == null) {
            return res;
        }

        int[] left = robDp(root.left);
        int[] right = robDp(root.right);

        res[1] = root.val + left[0] + right[0];
        res[0] = Math.max(left[0], left[1]) + Math.max(right[0], right[1]);

        return res;
    }
    public int rob(TreeNode root) {
        if(root == null) {
            return 0;
        }

        int[] res = robDp(root);

        return Math.max(res[0], res[1]);

    }
}