Day48 动态规划 part09
我的思路:
这次dp数组长度和nums相同,不需要额外的空间
状态转移方程为dp[i] = Math.max(dp[i - 2] + nums[i], dp[i - 1])
由于状态转移方程从i - 2开始,先给dp前两个数赋值,i = 0时,dp[0] = nums[0],dp[1] = Math.max(nums[0], nums[1])
解答:
class Solution {
public int rob(int[] nums) {
int[] dp = new int[nums.length];
if(dp.length == 1) {
return nums[0];
}
dp[0] = nums[0];
dp[1] = Math.max(nums[0], nums[1]);
for(int i = 2; i < dp.length; i++) {
dp[i] = Math.max(dp[i - 2] + nums[i], dp[i - 1]);
}
return dp[dp.length - 1];
}
}
我的思路:
分两种情况考虑
- 打劫第一间 ---- i 从0到 nums.length - 2,状态转移方程仍然是dp[i] = Math.max(dp[i - 2] + nums[i], dp[i - 1])
- 不打劫第一间 ---- i从1到nums.length - 1,状态转移方程dp[i] = Math.max(dp[i - 2] + nums[i + 1], dp[i - 1])
这道题把nums.length = 1和 = 2单独列出来返回了
解答:
class Solution {
public int rob(int[] nums) {
int[] dp = new int[nums.length - 1];
int[] dp1 = new int[nums.length - 1];
if(nums.length == 1) {
return nums[0];
}
if(nums.length == 2) {
return Math.max(nums[0], nums[1]);
}
dp[0] = nums[0];
dp[1] = Math.max(nums[0], nums[1]);
// 考虑第一间,不考虑最后一间
for(int i = 2; i < dp.length; i++) {
dp[i] = Math.max(dp[i - 2] + nums[i], dp[i - 1]);
}
dp1[0] = nums[1];
dp1[1] = Math.max(nums[1], nums[2]);
for(int i = 2; i < dp1.length; i++) {
dp1[i] = Math.max(dp1[i - 2] + nums[i + 1], dp1[i - 1]);
}
return Math.max(dp[dp.length - 1], dp1[dp1.length - 1]);
}
}
我的思路:
定义dp[0]表示不抢劫当前结点,dp[1]表示抢劫当前结点
递归遍历是左右中,从叶子结点向上回溯,叶子结点dp[1] = left[0] + right[0] + node.val = node.val;
dp[0] = Math.max(left[0], left[1]) + Math.max(right[0], right[1]) = 0;由此可得dp = [0, node.val],逐步网上推
解答:
class Solution {
public int rob(TreeNode root) {
int[] dp = new int[2];
dp = robTree(root);
return Math.max(dp[0], dp[1]);
}
public int[] robTree(TreeNode node) {
if(node == null) {
return new int[2];
}
int[] left = robTree(node.left);
int[] right = robTree(node.right);
int[] dp = new int[2];
dp[1] = left[0] + right[0] + node.val;
dp[0] = Math.max(left[0], left[1]) + Math.max(right[0], right[1]);
return dp;
}
}