题目来源
题目描述
class Solution {
public:
int rob(vector<int>& nums) {
}
};
题目解析
分析数据
0 <= nums[i] <= 1000
,全是正数,所以应该能抢则抢
思路
leetcode:198. 打家劫舍 I本质是基于一维数组的,而【打家劫舍 II】是一个环形数组。房子0和房子N-1成为了邻居,不能同时偷。
- 要么没有偷房子0
- 要么没有偷房子N-1
因此,我们将原数组拆成两部分
- nums[0],num[1]…num[end-1]
- nums[1],nums[2]…nums[end]
然后我们分别对这两个数组求最大值,这个求解过程就完全套用了【打家劫舍 I】的逻辑。
思路
class Solution {
// 至少有四家店
// 正在决策idx, 根据上一家店是不是被抢,来决定当前店抢不抢
// + preStatus表示上一家店有没有被抢过
// + endStatus表示N - 1店有没有被抢过: 因为endStatus会影响N - 2, 所以要带上
int process(vector<int>& nums, int idx, int preStatus, int endStatus){
int N = nums.size();
if(idx == N - 1){
return 0;
}
// N - 2店要被 preStatus和endStatus影响
if(idx == N - 2){
// 只要有前后两家店任何一个被抢过了,当前点就不能被抢
if(preStatus == 1 || endStatus == 1){
return 0;
}
int p1 = process(nums, idx + 1, 0, endStatus);
int p2 = process(nums, idx + 1, 1, endStatus) + nums[idx] ;
return std::max(p1, p2);
}
if(preStatus){ //preStatus被抢,当前店一定不能被抢
return process(nums, idx + 1, 0 , endStatus); //一定不能抢, 下一个决策的店是nums[idx + 1]
}else{ //preStatus为false,当前店可以抢也可以不抢
int p1 = process(nums, idx + 1, 0, endStatus );//一定不抢, 下一个决策的店是nums[idx + 1]
int p2 = process(nums, idx + 1, 1 , endStatus) + nums[idx] ; //可以抢
return std::max(p1, p2);
}
}
public:
int rob(vector<int>& nums) {
int N = nums.size();
if(N == 0){
return 0;
}
if(N == 1){
return nums[0];
}
if(N == 2){
return std::max(nums[0], nums[1]);
}
if(N == 3){
return std::max(nums[2], std::max(nums[0], nums[1]));
}
// 至少有4个店
// arr[0]比较特殊,它的前一家店是arr[N - 1]
// 将arr[0] 和arr[N - 1]绑定到一起
// 能做决策的店: 1 ~ N - 2
int p1 = nums[0] + process(nums, 1, 1, 0); // 1xxxx0
int p2 = process(nums, 1, 0, 1) + nums[N - 1];// 0xxxx1
int p3 = process(nums, 1, 0, 0); // 0xxxx0
return std::max(p1, std::max(p2, p3));
}
};
超时了,来优化的话就加缓存