你是一个专业的小偷,计划偷窃沿街的房屋,每间房内都藏有一定的现金。这个地方所有的房屋都 围成一圈 ,这意味着第一个房屋和最后一个房屋是紧挨着的。同时,相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警 。
给定一个代表每个房屋存放金额的非负整数数组,计算你 在不触动警报装置的情况下 ,能够偷窃到的最高金额。
示例 1:
Input: nums = [2,3,2]
Output: 3
Explanation: You cannot rob house 1 (money = 2) and then rob house 3 (money = 2), because they are adjacent houses.
示例 2:
Input: nums = [1,2,3,1]
Output: 4
Explanation: Rob house 1 (money = 1) and then rob house 3 (money = 3).
Total amount you can rob = 1 + 3 = 4.
示例 3:
Input: nums = [0]
Output: 0
提示:
- 1 ≤
nums.length
≤ 100 - 0 ≤
nums[i]
≤ 1000
思路
在打家劫舍1的基础上,分类讨论两种情况:
- 不偷第0家的方案;
- 不偷最后一家的方案;
- 两个方案里选一个价值最大的
代码
class Solution {
public:
int rob(vector<int>& nums) {
if( nums.size() == 0 ) return 0;
if( nums.size() == 1 ) return nums[0];
if( nums.size() == 2 ) return nums[0] > nums[1] ? nums[0] : nums[1];
int* dp_no_first = new int[ nums.size() ];
dp_no_first[0] = 0;
dp_no_first[1] = nums[1];
dp_no_first[2] = nums[1] > nums[2] ? nums[1] : nums[2];
for(int i = 3; i < nums.size(); i++) {
int take_it = nums[i] + dp_no_first[i-2];
int no_take = dp_no_first[i-1];
dp_no_first[i] = take_it > no_take ? take_it : no_take;
}
int max_no_first = *max_element(dp_no_first, dp_no_first + nums.size());
int* dp_no_last = new int[ nums.size() ];
dp_no_last[0] = nums[0];
dp_no_last[1] = nums[0] > nums[1] ? nums[0] : nums[1];
dp_no_last[ nums.size()-1 ] = 0;
for(int i = 2; i < nums.size()-1; i++) {
int take_it = nums[i] + dp_no_last[i-2];
int no_take = dp_no_last[i-1];
dp_no_last[i] = take_it > no_take ? take_it : no_take;
}
int max_no_last = *max_element(dp_no_last, dp_no_last + nums.size());
delete[] dp_no_first;
delete[] dp_no_last;
return max_no_first > max_no_last ? max_no_first : max_no_last;
}
};