198. 打家劫舍
题目
你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。
给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。
提示:
- 0 <= nums.length <= 100
- 0 <= nums[i] <= 400
解题思路
动态规划题目最主要的是找出状态转移方程。
这题可以分解成两种情况:(令N=nums.length+1)
①偷最后一间房子
也就是偷窃第4间房屋,那么就不能偷窃第3间房屋,偷窃总金额为前2间房屋的最高总金额与第 4 间房屋的金额之和。
②不偷最后一间房子。
不偷窃第 4间房屋,偷窃总金额为前3间房屋的最高总金额。
然后在两个选项中选择偷窃总金额较大的选项。
这样就可以找出状态转移方程:Math.max(dp[N \- 2] + nums[N- 1], dp[N \- 1]);
注意:
①这里的N-1
其实就是最后一间屋子了,因为假设有4间房子,那么N=4+1=5,所以dp的下标应该为[0,4]。所以N-1=4,就是dp数组的最后一个元素了。
②dp[N \- 1]
是指 前 N-1间房子能偷盗的最大值,不包括N-1那间房子。N-2也是同理。
代码
class Solution {
public int rob(int[] nums) {
if (nums.length == 0) {
return 0;
}
if (nums.length == 1) {
return nums[0];
}
int N = nums.length;
/*比如这里长度为N+1=4,那么最后返回的是dp[3]。因为下数组长度为4.下标就为0,1,2,3。
最后返回的就是dp[3],其实就是数组中的最后一个
*/
int[] dp = new int[N + 1];
//base case
dp[0] = 0;
dp[1] = nums[0];
dp[2] = Math.max(nums[0], nums[1]);
for (int i = 3; i <= N; i++) {
//状态转移方程
dp[i] = Math.max(dp[i - 2] + nums[i - 1], dp[i - 1]);
}
return dp[N];
}
}