House Robber II
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 arearranged 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.
此题思想是动态规划,声明两个变量,一个保存上一个被偷rob时最大值,另一个保存unrob上一个没有被偷的最大值,此时求下一个屋子是,rob=unrob+a[i];unrob=上一次rob和unrob的最大值(因为不一定是偷和被偷时交叉进行的,中间可能有连续几个不偷)。本题是将房子连成环,所以需要访问两次,一次没有最后一个,从0到len-2;一次没有第一个,从1到length-1,最后求最大,此题需要遍历两遍。
public class Solution { public int rob(int[] nums) { if(nums.length==1) return nums[0]; int rob=0; int unrob=0; for(int i=0;i<nums.length-1;i++){ int temp=unrob; unrob=Math.max(rob,unrob); rob=temp+nums[i]; } int res1=Math.max(unrob,rob); unrob=0; rob=0; for(int i=1;i<nums.length;i++){ int temp=unrob; unrob=Math.max(rob,unrob); rob=temp+nums[i]; } int res2=Math.max(unrob,rob); return Math.max(res1,res2); } }
还有一种写法,空间是O(n),一个数组表示第i个被偷,一个表示第i个没有被偷。代码如下。(非环)
public class Solution { public int rob(int[] num) { // 31 23 9 13 49 1 0 // 0 0 0 0 if(num==null || num.length==0) return 0; int n = num.length; int [] b = new int[n]; //include last element; int [] d = new int[n]; //exclude last element; b[0] = num[0]; d[0] = 0; for(int i=1; i<n; i++) { b[i] = d[i-1] + num[i]; d[i] = Math.max(b[i-1], d[i-1]); } return Math.max(d[n-1], b[n-1]); } }
维护一个数组,nums[i]表示到i时最大的钱数。
public class Solution { //1 2 3 public int rob(int[] nums) { if(nums==null || nums.length==0) return 0; if(nums.length==1) return nums[0]; if(nums.length==2) return Math.max(nums[0], nums[1]); return Math.max(robsub(nums, 0, nums.length-2), robsub(nums, 1, nums.length-1)); } private int robsub(int[] nums, int s, int e) { int n = e - s + 1; int[] d =new int[n]; d[0] = nums[s]; d[1] = Math.max(nums[s], nums[s+1]); for(int i=2; i<n; i++) { d[i] = Math.max(d[i-2]+nums[s+i], d[i-1]); } return d[n-1]; } }