力扣198.打家劫舍
题目链接:https://leetcode.cn/problems/house-robber/
思路
1.确定dp数组含义:dp[i]表示偷盗i个房子的最大价值为dp[i]。
2.递推公式:
(1)偷房子i,由于不能偷相邻房子,所以dp[i]=dp[i-2]+nums[i]
(2)不偷房子i,那么就由i-1个房子的状态决定,但是不一定会偷i-1个房子,所以dp[i]=dp[i-1]
(3)取二者最大值,dp[i] = Math.max(dp[i-2] + nums[i],dp[i-1])
3.初始化:
dp[0] = nums[0]
dp[1] = Math.max(nums[0],nums[1])
4.遍历顺序:从前向后
5.打印数组
完整代码
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-2] + nums[i],dp[i-1]);
}
return dp[nums.length-1];
}
}
力扣213.打家劫舍2
题目链接:https://leetcode.cn/problems/house-robber-ii/
思路
例如[2,3,2,3],把环转换成三种情况:
(1)不包含首尾,即[3,2]
(2)包含首,不包含尾,即[2,3,2]
(3)不包含首,包含尾,即[3,2,3]
事实上,情况2和3已经包含了情况1.将情况2和3分别求出,取最大值即可。
自己写的时候还是要注意下标溢出的问题。
完整代码
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]);
return Math.max(value(nums,0,nums.length-2),
value(nums,1,nums.length-1));
}
public int value(int[] nums,int start,int end){
int[] dp = new int[nums.length];
dp[start] = nums[start];
dp[start+1] = Math.max(nums[start],nums[start+1]);
for (int i = 2; i <= end; i++) {
dp[i] = Math.max(dp[i-2] + nums[i],dp[i-1]);
}
return dp[end];
}
}
力扣337.打家劫舍3
题目链接:https://leetcode.cn/problems/house-robber-iii/
思路
用一个长度为2的一维数组dp[]来表示当前节点是偷还是不偷:**dp[0]表示不偷当前节点所拥有的最大价值;dp[1]表示偷当前节点所拥有的最大价值。**那么,
(1)不偷当前节点,最大价值=左孩子偷还是不偷的最大价值+右孩子偷还是不偷的最大价值
(2)偷当前节点,那么它的左右孩子肯定不能偷了,最大价值=当前节点价值+左孩子不偷的最大价值+右孩子不偷的最大价值
1.确定递归参数和返回值:参数是传进去的节点。返回值是一个长度为2的一维数组,表示偷或不偷当前节点所拥有的最大价值
2.终止条件:当遍历到空结点,无论偷不偷,价值都是0
3.单层循环:
**
必须采用后序遍历,因为计算当前节点偷不偷的价值依靠左右孩子的返回值**
中节点的处理逻辑:
dp[1] = root.val + leftdp[0] +rightdp[0];
dp[0] = Math.max(leftdp[0],leftdp[1]) +
Math.max(rightdp[0],rightdp[1]);
左右孩子定义一个一维数组来接住返回值:
int[] leftdp = traversal(root.left);
int[] rightdp = traversal(root.right);
完整代码
class Solution {
public int rob(TreeNode root) {
int[] dp = traversal(root);
return Math.max(dp[0],dp[1]);
}
//dp[0]表示不偷,dp[1]表示偷
public int[] traversal(TreeNode root){
int[] dp = new int[2];
if(root == null) return dp;
int[] leftdp = traversal(root.left);
int[] rightdp = traversal(root.right);
dp[1] = root.val + leftdp[0] +rightdp[0];
dp[0] = Math.max(leftdp[0],leftdp[1]) +
Math.max(rightdp[0],rightdp[1]);
return dp;
}
}