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-2] 和 [1,n-1]之间结果的最大值,代码如下:
1 class Solution { 2 public: 3 int rob(vector<int>& nums) { 4 int n = nums.size(); 5 vector<int> dp(n,0); 6 if (n == 0) 7 return 0; 8 else if (n == 1 ) 9 return nums[0]; 10 else if (n == 2) 11 return max(nums[0],nums[1]); 12 else 13 return max(robCore(nums,0,n-1),robCore(nums,1,n)); 14 15 } 16 int robCore (vector<int>& nums, int left, int right) 17 { 18 vector<int> dp(nums.size(),0); 19 dp[left] = nums[left]; 20 dp[left+1] = max(nums[left],nums[left+1]); 21 for (int i = left+2; i < right; i++) 22 { 23 dp[i] = max(dp[i-1],dp[i-2]+nums[i]); 24 } 25 return dp[right-1]; 26 27 } 28 };
当然通过观察我们可以发现,其实只需要用两个变量,交替更新,就可以得到最后的结果,因此这道题最后可以简化为:
1 class Solution { 2 public: 3 int rob(vector<int>& nums) { 4 int n = nums.size(); 5 if(n == 0) return 0; 6 if(n ==1) return nums[0]; 7 return max(robber(nums, 0, n-2), robber(nums, 1, n-1)); 8 } 9 int robber(vector<int>&nums, int begin, int end){ 10 int pre = 0, cur = 0; 11 for(int i = begin; i<= end; i++){ 12 int tmp = max(pre+nums[i], cur); 13 pre = cur; 14 cur = tmp; 15 } 16 return cur; 17 } 18 };