來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/house-robber-ii/
題目
你是一個專業(yè)的小偷,計劃偷竊沿街的房屋,每間房內(nèi)都藏有一定的現(xiàn)金。這個地方所有的房屋都 圍成一圈 ,這意味著第一個房屋和最后一個房屋是緊挨著的。同時,相鄰的房屋裝有相互連通的防盜系統(tǒng),如果兩間相鄰的房屋在同一晚上被小偷闖入,系統(tǒng)會自動報警 。
給定一個代表每個房屋存放金額的非負(fù)整數(shù)數(shù)組,計算你 在不觸動警報裝置的情況下 ,今晚能夠偷竊到的最高金額。
示例 1:
輸入:nums = [2,3,2]
輸出:3
解釋:你不能先偷竊 1 號房屋(金額 = 2),然后偷竊 3 號房屋(金額 = 2), 因為他們是相鄰的。
示例 2:
輸入:nums = [1,2,3,1]
輸出:4
解釋:你可以先偷竊 1 號房屋(金額 = 1),然后偷竊 3 號房屋(金額 = 3)。
偷竊到的最高金額 = 1 + 3 = 4 。
示例 3:
輸入:nums = [0]
輸出:0
提示:
- 1 <= nums.length <= 100
- 0 <= nums[i] <= 1000
思路
參考leecode的題解,我們使用動態(tài)規(guī)劃的思路來解決。
根據(jù)題意,收尾數(shù)組不能同時偷,否則會觸發(fā)警報,那么可以將數(shù)組分為兩段,分別求出可收獲的最大金額,取最高的即可。
這里需要考慮特殊情況:
- 如果只有一家房屋,那直接偷就完事,renturn nums[0];
- 如果有兩件房屋,直接偷金額最多的屋子,return max(nums[0], nums[1]);
- 如果房屋數(shù)多于兩間,那么就可以分段,計算(0, n - 2)范圍的金額和(1, n - 1)范圍的金額,取最高的即可。
代碼
public int rob(int[] nums) {
int n = nums.length;
if (nums.length == 1) {
return nums[0];
} else if (nums.length == 2) {
return Math.max(nums[0], nums[1]);
} else {
return Math.max(robRange(nums, 0, n - 2), robRange(nums, 1, n - 1));
}
}
/**
分而治之:在確定的范圍內(nèi)使用動態(tài)規(guī)劃思路
*/
private static int robRange(int[] nums, int start, int end) {
int first = nums[start];
int second = Math.max(nums[start], nums[start + 1]);
int ret = 0;
for (int i = start + 2; i <= end; i++) {
int temp = second;
second = Math.max(first + nums[i], second);
first = temp;
}
return second;
}
結(jié)果

執(zhí)行結(jié)果