随想录Day48 | 198. 打家劫舍 、213. 打家劫舍 II 、337. 打家劫舍 III | 动态规划

88 阅读1分钟

198. 打家劫舍

题目链接:198. 打家劫舍

思路:

动规五部曲 

1.确定dp数组以及下标的含义

dp[i]:以下标为i的房子为重点的最高金额

2.确定递推公式

dp[i] = Math.max(dp[i - 1], dp[i - 2] + nums[i]);

3.dp数组如何初始化

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

4.确定遍历顺序

从前向后遍历

代码:

class Solution {
    public int rob(int[] nums) {
        if (nums.length == 1) return nums[0];
        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. 打家劫舍 II

题目链接:213. 打家劫舍 II

思路:

首尾房间不能同时被抢,那么只可能有三种不同情况:要么都不被抢;要么第一间房子被抢最后一间不抢;要么最后一间房子被抢第一间不抢。

其实,情况一的结果肯定最小,我们只要比较情况二和情况三就行了,因为这两种情况对于房子的选择余地比情况一大,房子里的钱数都是非负数,所以选择余地大,最优决策结果肯定不会小。

动规五部曲 

1.确定dp数组以及下标的含义

dp[i]:以下标为i的房子为重点的最高金额

2.确定递推公式

dp[i] = Math.max(dp[i - 1], dp[i - 2] + nums[i]);

3.dp数组如何初始化

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

4.确定遍历顺序

从前向后遍历

class Solution {
    public int rob(int[] nums) {
        int len = nums.length;
        if (len == 1) return nums[0];
        int result1 = robRange(nums, 0, len - 2);
        int result2 = robRange(nums, 1, len - 1);
        return Math.max(result1, result2);
    }

    public int robRange(int[] nums, int start, int end) {
        if (start == end) {
            return nums[start];
        }
        int[] dp = new int[nums.length];
        dp[start] = nums[start];
        dp[start + 1] = Math.max(nums[start], nums[start + 1]);

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

        return dp[end];
    }
    
}

337. 打家劫舍 III

题目链接:337. 打家劫舍 III

思路:
递归去偷,记录状态。

/**
 * 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 {

    Map<TreeNode, Integer> memo = new HashMap<>();

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

    int robAction(TreeNode root) {
        if (root == null) {
            return 0;
        }
        if (memo.containsKey(root)) {
            return memo.get(root);
        }
        int money = root.val;
        if (root.left != null) {
            money += robAction(root.left.left) + robAction(root.left.right);
        }
        if (root.right != null) {
            money += robAction(root.right.left) + robAction(root.right.right);
        }
        money = Math.max(money, robAction(root.left) + robAction(root.right));
        memo.put(root, money);
        return money;
    }
}