198.打家劫舍(中等)
-
思路
- 定义数组 dp, dp[i] 表示抢劫到第 i 个房子的时候,可以抢劫的最大数量。
- dp[i] 有两种可能:一种是我们选择不抢劫这个房子,此时累积金额为 dp[i-1] ;另一种是我们选择抢劫这个房子,那么此前累积的最大金额只能是 dp[i-2] ,因为我们不可能抢劫第 i-1 个房子,否则会触发警报机关。
- 因此,本题的状态转移方程为:
dp[i] = max(dp[i-1], dp[i-2] + nums[i-1]);
-
代码
class Solution { public: int rob(vector<int>& nums) { int n = nums.size(); if(n == 1) return nums[0]; vector<int> dp(n+1, 0); dp[1] = nums[0]; for(int i=2; i<=n; ++i){ dp[i] = max(dp[i-1], nums[i-1] + dp[i-2]); } return dp[n]; } };
空间压缩
class Solution { public: int rob(vector<int>& nums) { int n = nums.size(); if(n == 1) return nums[0]; int pre1 = 0, pre2 = 0; int ans = 0; for(int i=0; i<n; ++i){ ans = max(pre1, pre2 + nums[i]); pre2 = pre1; pre1 = ans; } return ans; } };
-
收获
- 题解的思路只考虑到两个状态,比较简单。我自己做题的时候,使用的状态转移方程为:
dp[i] = max(dp[i-2] + nums[i], dp[i-3] + nums[i])
,除了初始化定义的 dp[0] = 0 ,还需要计算 dp[1]、 dp[2]、 dp[3] 三个初始状态,比较繁琐,最后返回的时候也需要比较max(dp[n-1], dp[n-2]);
- 我这里的 dp[i] 从 dp[0] 开始 ;而题解则是从 dp[1] 开始,理解起来也更方便,值得学习。
- 题解的思路只考虑到两个状态,比较简单。我自己做题的时候,使用的状态转移方程为: