题目:
Note: This is an extension of 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.
思路:
如果窃取了第0号房子,那么就不能再窃取第n-1号房子;而如果不窃取第0号房子,那么就可以窃取第n-1号房子。所以我们可以将窃取方案按照是否窃取第0号房子分为两种类型,而每种类型的解法和House Robber的完全相同,我们最后取获利最大者即可。
假设dp[i]代表截止第i个房子可以获得的最大利润,那么递推公式为:dp[i] = max(dp[i-1], dp[i - 2] + nums[i])。可以看出dp[i]仅仅与dp[i-1]和dp[i-2]相关,所以我们可以进一步将空间复杂度从O(n)降低到O(1)。具体实现见下面的代码片段。
代码:
class Solution {
public:
int rob(vector<int>& nums) {
int size = nums.size();
if(size == 0) {
return 0;
}
else if(size == 1) {
return nums[0];
}
return max(robBetween(nums, 0, size - 2), robBetween(nums, 1, size - 1));
}
private:
int robBetween(vector<int>& nums, int start, int end) {
if(start == end) {
return nums[start];
}
int value0 = nums[start];
int value1 = max(value0, nums[start + 1]);
for(int i = start + 2; i <= end; ++i) {
int max_value = max(value0 + nums[i], value1);
value0 = value1;
value1 = max_value;
}
return value1;
}
};