房屋圍成一圈,首尾相鄰。每間房有非負金額,偷相鄰房會觸發警報。求最大可偷金額。
首尾不能同時偷,分兩種情況取最大:
答案 = max(rob_linear(1,n-1), rob_linear(0,n-2))
int rob_range(vector& nums, int l, int r) { // 閉區間 [l, r]
int prev = 0, curr = 0;
for (int i = l; i <= r; ++i) {
int next = max(curr, prev + nums[i]);
prev = curr;
curr = next;
}
return curr;
}
int rob(vector& nums) {
int n = nums.size();
if (n == 0) return 0;
if (n == 1) return nums[0];
if (n == 2) return max(nums[0], nums[1]);
return max(rob_range(nums, 0, n-2), rob_range(nums, 1, n-1));
}
原文提出從左向右、從右向左兩次 DP,比較 `d[n-1]` vs `d[n-2]` 和 `dr[1]`,邏輯等價但較繁瑣。拆環法更直觀。
`dp[i] = max(dp[i-1], dp[i-2] + nums[i])`:
- 不偷第 i 間:沿用 `dp[i-1]`
- 偷第 i 間:必須不偷 i-1,加上 `dp[i-2] + nums[i]`
| n | 處理 |
|---|---|
| 0 | 返回 0 |
| 1 | 返回 nums[0] |
| 2 | 返回 max(nums[0], nums[1]) |
| ≥3 | 拆環取最大 |