打家劫舍
这道题也算是一道挺经典的题,即使不了解动态规划的人肯定也见过这道题。先来看代码
class Solution {
public:
int rob(vector<int>& nums) {
if(nums.size() <= 1){
return nums.size() == 0 ? 0 : nums[0];
}
// a是上次的最大收益
int a = nums[0];
// b是当前的最大受益
int b = max(nums[0], nums[1]);
for(int i = 2; i < nums.size(); i++){
int tmp = b;
// 当前的最大收益是两种选择里较大的那个
b = max(a + nums[i], b);
a = tmp;
}
return b;
}
};
如上图所示,某一次我们遍历到图中指向的那间房子,那么我们有两种选择,要么跳过当前的房子,要么选择当前的房子。我们要明白一点,任意前m间房子的选择结果一定是最优的,所以我们在选择时也要比较这两种选择,选出最优的结果。
现在唯一的问题就是怎么比较这两种选择哪一个比较好。因为题中要求不能选择连续的两间房子,所以我们就有如图所示的两种选择方式,分别用绿色和红色圈出。
我们设当前选择到了第m间房子,那第一种选择可以简化为前m-2间房子的最优选择再加上当前第m间房子;第二种选择可以简化为前m-1间房子的最优选择。我们只要用两个变量记录这两个值然后进行比较即可得到当前最优选择。
这里还有第二种解法,算法思想依然是一样的,不过采用的是倒着遍历,下面是代码,有兴趣的可以了解一下
class Solution {
public:
int rob(vector<int>& nums) {
if(nums.empty()) return 0;
int n=nums.size();
vector<int> result(n+1,0);
result[n]=0;result[n-1]=nums[n-1];
for(int i=n-2;i>=0;i--){
result[i]=max(nums[i]+result[i+2],result[i+1]);
}
return result[0];
}
};
网友评论