题目链接:点击这里
暴力搜索,时间复杂度 O ( 2 n ) O(2^n) O(2n),超时。
class Solution {
public:
int solve(int index, vector<int>& nums) {
if(index < 0) return 0;
return max(nums[index]+solve(index-2, nums), solve(index-1, nums));
// 抢index店后就只能抢index-2店,不抢index店就可以抢相邻的店
// 两者取最大值
}
int rob(vector<int>& nums) {
return solve(nums.size()-1, nums);
}
};
在上面暴力递归的基础上,开一个数组记录结果,去掉重复计算,AC:
/* 记忆化搜索:每个状态只计算一次,总共有n个状态 O(n) */
class Solution {
public:
int *result; //全局数组
int solve(int index, vector<int>& nums) {
if(index < 0) return 0;
if(result[index] >= 0) return result[index]; //算过就直接返回结果
result[index] = max(nums[index]+solve(index-2, nums), solve(index-1, nums));
return result[index];
// 抢index店后就只能抢index-2店,不抢index店就可以抢相邻的店,两者取最大值
}
int rob(vector<int>& nums) {
result = new int[nums.size()];
for(int i = 0; i < nums.size(); i++) //初始化为-1
result[i] = -1;
return solve(nums.size()-1, nums);
}
};
递归自顶向下,递推自底向上。
将递归改为递推就得到了动态规划的解法,如下。
可以看到代码就不是很漂亮了,需要处理很多边界情况,但速度确实快了不少。
class Solution {
public:
int *result; //全局数组
int rob(vector<int>& nums) {
if(nums.size() == 0) return 0; //一家店也没有,返回0
if(nums.size() == 1) return nums[0]; //只有一家店,返回一家店
result = new int[nums.size()];
result[0] = nums[0]; //需要处理边界
result[1] = max(nums[0], nums[1]);
for(int index = 2; index < nums.size(); index++)
result[index] = max(nums[index]+result[index-2], result[index-1]);
return result[nums.size()-1];
}
};