思路:总的把情况分为三种:
第一种:只有一间房,那么偷窃到的最大金额就是这间房的金额。
第二种:只有两间房:那么偷窃到的最大金额就是这两间房的较大值。
第三种:有k(k>2)间房,那么偷窃到的金额又可分为两种情况:
- 偷第k间房,则不能偷k-1间房,偷窃总金额为偷前k-2间房屋的最高总金额与第k间房屋的金额之和。
- 不偷第k间房,则偷窃总金额为前k-1间房屋的最高总金额。
以上两种情况我们应该取较大值,即为偷窃前k间房屋的最高总金额。
用 dp[i] 表示前 ii 间房屋能偷窃到的最高总金额,那么就有如下的状态转移方程:
dp[i] = Math.max(dp[i-2]+nums[i],dp[i-1])
第一种情况和第二种情况即为边界条件。最终答案就是dp[n-1];
class Solution {
public int rob(int[] nums) {
int n = nums.length;
// 没有元素时
if (nums == null || n == 0) {
return 0;
}
// 有一个元素时
if (n == 1) {
return nums[0];
}
// 有两个元素时
if (n == 2) {
return Math.max(nums[0], nums[1]);
}
// 有三个及三个以上元素时
// dp[i] 表示偷窃前i(包括i)个房子的最大金额
int[] dp = new int[n];
dp[0] = nums[0];
dp[1] = Math.max(nums[0], nums[1]);
for (int i = 2; i < n; i++) {
dp[i] = Math.max(dp[i - 2] + nums[i], dp[i - 1]);
}
return dp[n - 1];
}
}
优化:滚动数组优化
class Solution {
public int rob(int[] nums) {
int n = nums.length;
// 没有元素时
if (nums == null || n == 0) {
return 0;
}
// 有一个元素时
if (n == 1) {
return nums[0];
}
// 有两个元素时
if (n == 2) {
return Math.max(nums[0], nums[1]);
}
// 有三个及三个以上元素时
// 前k-2间偷窃的最总高金额
int first = nums[0];
// 前k-1间偷窃的最总高金额
int second = Math.max(nums[0], nums[1]);
for (int i = 2; i < n; i++) {
int temp = second;
second = Math.max(first + nums[i], second);
first = temp;
}
return second;
}
}