1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
|
class Solution {
//DP: consider circle nums, nums[0], nums[length-1] are adjacent, so we can divide nums into two line new nums such as nums1: nums[0] -num[length-2] , nums2: nums[1] -num[length-1],
// and get maximum = Math.max( rob(nums1), rob(nums2))
//將環狀house,拆為線型house,讓首尾house不再相連,簡化問題,即将nums 拆分為2個數組, 從而把打家劫舍robII 转化为 打家劫舍rob
public int rob(int[] nums) {
if (nums == null || nums.length == 0) {
return 0;
}
if (nums.length == 1) {
return nums[0];
}
//從第一家開始打劫,直到nums[nums.length - 2], start to rob from the first house nums[0], so not consider to rob the last house nums[length-1]
int robFromFirst = robLinear(nums, 0, nums.length - 2);
//從第二家開始打劫,直到nums[nums.length - 1], start to rob from the second house num[1], so consider to rob the last house nums[length-1]
int robFromSecond = robLinear(nums, 1, nums.length - 1);
return Math.max(robFromFirst, robFromSecond);
}
public int robLinear(int[] nums, int start, int end) {
if (start == end) {
return nums[start];
}
int[] dp = new int[nums.length];
dp[start] = nums[start];
dp[start+1] = Math.max(nums[start], nums[start + 1]);
for (int i = start + 2; i <= end; i++) {
//dp[i] 可以分為 rob | 不rob 當前stores[i],取二者中的較大值
dp[i] = Math.max(dp[i - 2] + nums[i], dp[i - 1]);
}
return dp[end];
}
private int robLinear2(int[] houses, int start, int end) {
if (start == end) {
return houses[start];
}
int n = end - start + 1;
int[] dp = new int[n];
//注意处理初始化值,与dp[n]数组
dp[0] = houses[start];
dp[1] = Math.max(houses[start], houses[start + 1]);
for (int i = 2; i < n; i++) {
dp[i] = Math.max(dp[i - 1], dp[i - 2] + houses[start + i]);
}
return dp[n - 1];
}
}
|