方法一:简单搜索(超出内存限制)
对于每一家i
,选择抢或不抢,若不抢,则可对i+1
进行选择;若抢,则对i+2
进行选择
class Solution {
public:
int rob(vector<int>& nums) {
if(nums.size()==0) return 0;//空集特判
return rec(nums,0);
}
int rec(vector<int>nums,int i){//从第i个住户开始rob
int res;
if(i>=nums.size()) res=0;//非法下标
else if(i+1>=nums.size()) res=nums[i];//若下标为最后一个,则只能抢来保证金额最大
else res=max(rec(nums,i+1),rec(nums,i+2)+nums[i]);//选择抢和不抢i两种情况
return res;
}
};
方法二:记忆化搜索(时间和空间效率还是很差)
class Solution {
private:
int dp[1000000];//dp数组进行记忆
public:
int rob(vector<int>& nums) {
memset(dp,-1,sizeof(dp));//初始化dp数组
if(nums.size()==0) return 0;
return rec(nums,0);
}
int rec(vector<int>nums,int i){//从第i个住户开始rob
if(dp[i]>=0) return dp[i];//若已经计算过,则直接返回
int res;
if(i>=nums.size()) res=0;
else if(i+1>=nums.size()) res=nums[i];
else res=max(rec(nums,i+1),rec(nums,i+2)+nums[i]);//选择走不走i两种情况
return dp[i]=res;//维护dp数组
}
};
方法三:穷竭搜索(超出内存限制)
class Solution {
public:
int rob(vector<int>& nums) {
if(nums.size()==0) return 0;
return rec(nums,0,0);
}
int rec(vector<int>nums,int i,int sum){//从第i个住户开始rob
int res;
if(i>=nums.size()) res=sum;
else if(i+1>=nums.size()) res=nums[i]+sum;
else res=max(rec(nums,i+1,sum),rec(nums,i+2,sum+nums[i]));//选择走不走i两种情况
return res;
}
};
方法四:动态规划(和记忆化搜索效率差不多)
class Solution {
private:
int dp[1000000];//初始化为0
public:
int rob(vector<int>& nums) {
int n=nums.size();
for(int i=n-1;i>=0;i--){
if(i+1>=n) dp[i]=nums[i];
else dp[i]=max(dp[i+1],dp[i+2]+nums[i]);
}
return dp[0];
}
};
写成i
正向递推,效率相同。但是若dp定义为动态数组,则效率会大大增加:
class Solution {
private:
int dp[1000000];
public:
int rob(vector<int>& nums) {
int n=nums.size(); if(n==0) return 0;
//int *dp=new int[n+1];//定义动态数组
dp[0]=0; dp[1]=nums[0];
for(int i=0;i<=n-2;i++)
dp[i+2]=max(dp[i+1],dp[i]+nums[i+1]);
return dp[n];
}
};