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.
难点在于当你走到最后一个位置判断时你不清楚第一个位置上的是否已经被包括进去了。。
不过由此假设,如果最多的那条线包含第一个位置的,那 1~n 和 1~n-1 的范围实际上是一致的,而如果位置 n 包含其中,那同理 1~n 和 2~n 也是一致的,问题就变成和前面那个一样的了
所以可以类似地遍历两次,分别是 1~n-1 和 2~n,由此比较两个范围的最大值
public class Solution {
public int rob(int[] nums) {
if(nums==null || nums.length==0) return 0;
if(nums.length==1) return nums[0];
int[][] price = new int[nums.length][2];
int max = 0;
price[0][0] = 0;price[0][1] = nums[0];
max = Math.max(max, Math.max(price[0][0], price[0][1]));
for(int i=1; i<nums.length-1; i++){
price[i][0] = Math.max(price[i-1][0], price[i-1][1]);
price[i][1] = price[i-1][0] + nums[i];
max = Math.max(max, Math.max(price[i][0], price[i][1]));
}
price[1][0] = 0;price[1][1] = nums[1];
max = Math.max(max, Math.max(price[1][0], price[1][1]));
for(int i=2; i<nums.length; i++){
price[i][0] = Math.max(price[i-1][0], price[i-1][1]);
price[i][1] = price[i-1][0] + nums[i];
max = Math.max(max, Math.max(price[i][0], price[i][1]));
}
return max;
}
}
写得有点复杂了。。。不需要用二维数组也能做到,两个变量就行
public int rob(int[] nums) {
if (nums.length == 1) return nums[0];
return Math.max(rob(nums, 0, nums.length - 2), rob(nums, 1, nums.length - 1));
}
private int rob(int[] num, int lo, int hi) {
int include = 0, exclude = 0;
for (int j = lo; j <= hi; j++) {
int i = include, e = exclude;
include = e + num[j];
exclude = Math.max(e, i);
}
return Math.max(include, exclude);
}