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.
[balabala] 数组表示环后,根据题意,最后一个元素不能和第一个元素同时参与计算,为此可使用两个dp数组将题目重新简化为非环的House Robber, dp[] 用于计算0 号 房子 到 n - 2 号房子能抢到的最大金额,dp2[]用于计算 1号房子 到 n - 1号房子能抢到的最大金额,最后取两个dp数组最后元素的最大值。
// method 1
public int rob(int[] nums) {
if (nums == null || nums.length == 0)
return 0;
int n = nums.length;
if (n == 1)
return nums[0];
if (n == 2)
return Math.max(nums[0], nums[1]);
int[] dp = new int[n - 1];
int[] dp2 = new int[n - 1];
dp[0] = nums[0];
dp[1] = Math.max(dp[0], nums[1]);
dp2[0] = nums[n - 1];
dp2[1] = Math.max(dp2[0], nums[0]);
for (int i = 2; i < n - 1; i++) {
dp[i] = Math.max(dp[i - 2] + nums[i], dp[i - 1]);
}
for (int i = 1; i < n - 2; i++) {
dp2[i + 1] = Math.max(dp2[i - 1] + nums[i], dp2[i]);
}
return Math.max(dp[n - 2], dp2[n - 2]);
}
// method 2
// 变成环形后,第一家和最后一家不能同时取,因此分两种情况讨论,
// 调用原House Robber中的方法两次, 取较大值
public int rob2(int[] nums) {
if (nums == null || nums.length == 0)
return 0;
int n = nums.length;
if (n == 1)
return nums[0];
return Math.max(robLinear(nums, 0, n - 2), robLinear(nums, 1, n - 1));
}
private int robLinear(int[] nums, int start, int end) {
int[] dp = new int[end - start + 2];
int n = dp.length;
dp[0] = 0;
dp[1] = nums[start];
for (int i = start + 1; i <= end; i++) {
int k = i - start + 1;
dp[k] = Math.max(dp[k - 1], dp[k - 2] + nums[i]);
}
return dp[n - 1];
}

194

被折叠的 条评论
为什么被折叠?



