198. 打家劫舍
解法一
dp数组:
dp[i][0]
:不偷下标为 i 的房屋时,偷窃前 i 个房屋能获得的最大金额dp[i][1]
:偷下标为 i 的房屋时,偷窃前 i 个房屋能获得的最大金额
最终结果:max(dp[n-1][0], dp[n-1][1])
在计算dp[i][x]
时:
dp[i][0]
:问题转换为偷窃前 i-1 个房屋能获得的最大金额:dp[i][0] = max(dp[i-1][0], dp[i-1][1])
dp[i][1]
:- 此时不能偷第 i-1 个房屋
- 可以先在前 i-1 个房屋中进行偷窃,但不偷第 i-1 个房屋,然后再偷第 i 个房屋:
dp[i][1] = dp[i-1][0] + nums[i]
递推公式:
dp[i][0] = Math.max(dp[i-1][0], dp[i-1][1]);
dp[i][1] = dp[i-1][0] + nums[i];
递推公式适用范围:令递推公式中所有下标都大于等于0小于n,即i >= 0, i-1 >= 0, i < n, i-1 < n
,计算得到:1 <= i < n
计算顺序:在计算dp[i][x]
时需要用到dp[i-1][x]
,因此应该从前向后计算i = 0 -> n-1
初始化:
可以使用递推公式进行计算的范围是1 <= i < n
,因此需要对 i = 0
的情况进行初始化
class Solution {
public int rob(int[] nums) {
int n = nums.length;
// dp[i][0]:不偷下标为 i 的房屋时,偷窃前 i 个房屋能获得的最大金额
// dp[i][1]:偷下标为 i 的房屋时,偷窃前 i 个房屋能获得的最大金额
int[][] dp = new int[n][2];
// 初始化
dp[0][0] = 0;
dp[0][1] = nums[0];
// 递推计算
for(int i = 1; i < n; i++){
dp[i][0] = Math.max(dp[i-1][0], dp[i-1][1]);
dp[i][1] = dp[i-1][0] + nums[i];
}
// 返回结果
return Math.max(dp[n-1][0], dp[n-1][1]);
}
}
解法二
这是解法一的递推公式:
dp[i][0] = Math.max(dp[i-1][0], dp[i-1][1]);
dp[i][1] = dp[i-1][0] + nums[i];
对于其中的第二个式子dp[i][1] = dp[i-1][0] + nums[i]
,如果将d