题目:
题解:
- 题解1:关于题解1的代码若理解起来确实比较困难的话,倒不如直接看题解2的动态规划解法,因为题解1的做法跟dp做法一样的,只是没有用dp数组来保存每个状态i的值,而是每次都更新sum0和sum1,确定sum0或sum1要么为房间i-1房屋可盗窃的最大值,要么就是i-2房屋可盗窃的最大值加上当前房屋的值num[i]。
- 题解2:动态规划
- dp[i]表示房间i获得最大金额数。
- 状态转移方程
dp[i]=max(dp[i-1],dp[i-2]+nums[i-1]);
表示:在房间i可盗窃的最大值,要么就是i-1房屋可盗窃的最大值,要么就是i-2房屋可盗窃的最大值加上当前房屋的值,二者之间取最大值。
代码如下:
class Solution {
public:
//思路1:sum0对奇数项求和,sum1对偶数项求和,注意在每次求和之后,需要更新为sum0和sum1中的较大值
int rob_1(vector<int>& nums) {
if(nums.empty())return 0;
int sum0=0,sum1=0;
for(int i=0;i<nums.size();++i){
if(i%2==0){
sum0+=nums[i];
//房间i的最大值要么是sum0的值(房间i-2的最大值+当前房间的值nums[i]),要么是sum1的值(房间i-1的最大值),二者取较大值即可
sum0=max(sum0,sum1);
}
else{
sum1+=nums[i];
//房间i的最大值要么是sum0的值(房间i-2的最大值+当前房间的值nums[i]),要么是sum1的值(房间i-1的最大值),二者取较大值即可 sum1=max(sum0,sum1);
}
}
//最后一次返回sum0和sum1中的较大值
return max(sum0,sum1);
}
//题解2:动态规划,与上面思路一样的,不过换为动态规划更好理解
int rob(vector<int>& nums){
if(nums.empty())return 0;
int n=nums.size(),dp[n+1];
memset(dp,0,sizeof(dp));
dp[1]=nums[0];
for(int i=2;i<=n;++i){
//在房间i可盗窃的最大值,要么就是i-1房屋可盗窃的最大值,要么就是i-2房屋可盗窃的最大值加上当前房屋的值,二者之间取最大值
dp[i]=max(dp[i-1],dp[i-2]+nums[i-1]);
}
return dp[n];//返回房间n偷到的最大金额数
}
};