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.
Credits:
Special thanks to @Freezen for adding this problem and creating all test cases.
续接前面的House Robber I 但是想了好久都没想出来怎么解。加上条件的DP问题需要进行一定的转化才能成为标准的DP问题,这个转化就成了关键。
这里的关键就是最后那一个房间N和第一个房间相连了,可以这么进行转化:
考虑抢劫了第0个房间,那么问题就是求抢劫第0~N-1个房间的最大数。
考虑不抢劫第0个房间,那么问题就是求抢劫第1~N个房间的最大数。
上面转化后的两个问题就是House Robber I中的问题。再求上面两个解的最大值,就是本题的解。
在做这题时发现House Robber I中的代码还可以进一步的优化,可以将数组也省略掉而只使用两个变量来存储值,这样空间复杂度也降到了O(1)。代码更优了。
这是因为House Robber I只需要比较第A[i-2]+nums[i]和A[i-1]的大小,所以可以把House Robber I中的数组也省略掉,而只需要两个变量来存储着两个值,这样更能节约空间。这里pLast存储的是House Robber I中A[i-1]的值,ppLast存储的是House Robber I中A[i-2]的值,逻辑和House Robber I是一样的。
runtime:0ms
class Solution { public: int rob(vector<int>& nums) { int length=nums.size(); if(length==0) return 0; if(length==1) return nums[0]; return max(robDiv(nums,0,length-2),robDiv(nums,1,length-1)); } int robDiv(vector<int> &nums,int first,int last) { //因为只需要比较第A[i-2]+nums[i]和A[i-1]的大小,所以可以把House Robber I中的数组也省略掉, //而只需要两个变量来存储着两个值,这样更能节约空间。 //这里pLast存储的是House Robber I中A[i-1]的值, //ppLast存储的是House Robber I中A[i-2]的值,逻辑和House Robber I是一样的。 int pLast=0,ppLast=0; for(int i=first;i<=last;i++) { int tmp=pLast; pLast=max(ppLast+nums[i],pLast); ppLast=tmp; } return pLast; } };