一、题目
198. 打家劫舍
213. 打家劫舍 II
337. 打家劫舍 III
二、分析
- 第一题:
[2,7,9,3,1]
进了第一个房间:偷盗最大值:2
进了第二个房间:7 > 2,所以不偷第一个房间只偷第二个房间,偷盗最大值:7
进了第三个房间,两种情况:偷:用第一个房间时已偷盗的最大值 + nums[i];不偷:等于第二个房间时偷盗的最大值。
\-----------------------\
只需要记录两个值,进一个新房间前,偷到的最大值cur;和进入前一个房间之前偷盗的最大值pre.
- 第二题:
加了一个限定:第一个房间和最后一个房间不能同时偷。注意:这两个房间可能都偷不到!比如:[1, 9, 2]
。
所以可以将他们截断:从[1~n-1]
房间中偷,和从[2~n]
房间中偷,最后比较较大值。
- 本来打算使用标记记录第一个房间有没有偷,但是在值的传递关系中有很大问题。
- 第三题
待更新
三、代码
- 第一题
class Solution {
public:
int rob(vector<int>& nums) {
int n(nums.size());
if(n == 1) return nums[0];
// 只需要记录两个值,进一个新房间时,偷到的最大值cur;和前一个房间前偷盗的最大值pre
// 因为进一个新房间有两种情况:偷:用pre加上新房间的物品;不偷:还是等于cur。
int pre(nums[0]), cur(max(nums[1],nums[0])), temp(0);
for(int i = 2; i < n; i++){
temp = cur;
cur = max(cur, pre + nums[i]);
pre = temp;
}
return cur;
}
};
执行用时:4 ms, 在所有 C++ 提交中击败了40.09%的用户
内存消耗:7.5 MB, 在所有 C++ 提交中击败了84.58%的用户
- 第二题
class Solution {
public:
int rob(vector<int>& nums) {
int n(nums.size());
if(n == 1) return nums[0];
int result1 = robRange(nums, 0, nums.size() - 2); // 情况二
int result2 = robRange(nums, 1, nums.size() - 1); // 情况三
return max(result1, result2);
}
int robRange(vector<int> nums, int s, int e){
if(s == e) return nums[s];
int pre(nums[s]), cur(max(nums[s+1],nums[s])), temp(0);
for(int i = s+2; i <= e; i++){
temp = cur;
cur = max(cur, pre + nums[i]);
pre = temp;
}
return cur;
}
};
执行用时:0 ms, 在所有 C++ 提交中击败了100.00%的用户
内存消耗:7.8 MB, 在所有 C++ 提交中击败了53.37%的用户
- 第三题