198. House Robber
MediumDescription
一排房屋各有不同金額,相鄰的房屋不能同時被搶。給定代表每間房屋金額的整數陣列
nums,求在不觸發警報的情況下能搶到的最大金額。
Example:
Input: nums = [2,7,9,3,1] Output: 12
Intuition#
每間房屋只有兩種選擇:搶或不搶。搶了就跳過下一間,不搶則繼續。
- 對於第
i間房屋:搶 →dp[i-2] + nums[i],不搶 →dp[i-1] - 狀態轉移:
dp[i] = max(dp[i-1], dp[i-2] + nums[i]) - 經典的「取或不取」DP 模式
Approaches#
1: Bottom-Up DP Array#
- 概念: 建立 DP 陣列紀錄到每間房屋為止的最大收益
- 時間複雜度:
O(n) - 空間複雜度:
O(n)
class Solution {
fun rob(nums: IntArray): Int {
if (nums.size == 1) return nums[0]
val dp = IntArray(nums.size)
dp[0] = nums[0]
dp[1] = maxOf(nums[0], nums[1])
for (i in 2 until nums.size) {
dp[i] = maxOf(dp[i - 1], dp[i - 2] + nums[i])
}
return dp[nums.size - 1]
}
}⭐2: Rolling Variables#
- 概念: 只需要前兩個狀態,用兩個變數即可
- 時間複雜度:
O(n) - 空間複雜度:
O(1)
class Solution {
fun rob(nums: IntArray): Int {
var prev2 = 0
var prev1 = 0
for (num in nums) {
val cur = maxOf(prev1, prev2 + num)
prev2 = prev1
prev1 = cur
}
return prev1
}
}🔑 Takeaways#
- Pattern: 取或不取 (Take or Skip) — 每個元素有兩種決策,取了就跳過相鄰元素
- 關鍵技巧:
prev2代表「不包含前一個」的最大值,prev1代表「包含或不包含前一個」的最大值