声明:原题目转载自LeetCode,解答部分为原创
Problem :
Note: This is an extension of House Robber. [LeetCode] House Robber
After robbing those houses on that street, the thief has found himself a new place for his thievery so that he will not get too much attention. This time, all houses at this place are arranged in a circle. That means the first house is the neighbor of the last one. Meanwhile, the security system for these houses remain the same as for those in the previous street.
Given a list of non-negative integers representing the amount of money of each house, determine the maximum amount of money you can rob tonight without alerting the police.
Solution:
思路:按照题意,给定一个首尾相连的循环数组array[ length ],要求的是满足“元素两两不相邻”的子序列的最大和。由上一道题,我们可以得出一个array[ ]数组中的“满足两两不相邻”条件的子序列的最大和。考虑本题的特殊之处在于“首间房子跟尾间房子不能同时抢劫”,可能有以下三种情况:
(1)目标子序列不包含array[ ]数组的第一个元素,但包含最后一个元素,结果等价于array[ 1, length - 1 ]在线性数组情景下的返回值;
(2)目标子序列不包含array[ ]数组的最后一个元素,但包含第一个元素,结果等价于array[ 0, length - 2 ]在线性数组情景下的返回值;
(3)目标子序列既不包含数组的第一个元素,也不包含最后一个元素,结果等价于array[ 1, length - 1] 和array[ 0, length - 2 ]的相同返回值;
则调用两次线性数组情景下的函数,返回其中较大的值。代码如下:
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 max(nums[0], nums[1]);
if(nums.size() == 3)
return max( max(nums[0], nums[1]), nums[2]);
vector<int> temp_1(nums.size() - 1);
vector<int> temp_2(nums.size() - 1);
temp_1.assign(nums.begin(), nums.end() - 1);
temp_2.assign(nums.begin() + 1, nums.end());
int result_1 = find_max_money(temp_1);
int result_2 = find_max_money(temp_2);
return max(result_1, result_2);
}
private:
int find_max_money(vector<int> &array)
{
vector<int> max_money(array.size());
max_money[0] = array[0];
max_money[1] = array[1];
max_money[2] = max(array[0] + array[2], array[1]);
int result = max( max(max_money[0], max_money[1]), max_money[2] );
for(int i = 3; i < array.size(); i ++)
{
max_money[i] = array[i] + max(max_money[i - 2], max_money[i - 3]);
result = max(result, max_money[i]);
}
return result;
}
};