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;
}
}