198. 打家劫舍
Origin: LeetCode 198
题目描述
你是一个小偷,沿街排列的房屋中每间都有一定的金额。不能偷相邻的两间房,否则会报警。求能偷到的最大金额。
示例
Input: nums = [1, 2, 3, 1]
Output: 4
Explanation: 偷第 1 间(金额 1)和第 3 间(金额 3),共 4。
Input: nums = [2, 7, 9, 3, 1]
Output: 12
Explanation: 偷第 1 间(2)+ 第 3 间(9)+ 第 5 间(1)= 12。
约束
- 1 <= nums.length <= 100
- 0 <= nums[i] <= 400
关键信息
- 不能偷相邻两间
- dp[i] = max(dp[i-1], dp[i-2] + nums[i])
- 可优化为 O(1) 空间(和最大子数组和一样的滚动变量)
Resolution
我的解法
function rob(nums: number[]): number {
if (!nums.length) return 0
if (nums.length <= 2) {
return Math.max(...nums)
}
const dp: number[] = [nums[0], Math.max(nums[0], nums[1])]
for (let i = 2; i < nums.length; i++) {
dp[i] = Math.max(dp[i - 1], dp[i - 2] + nums[i])
}
return dp[dp.length - 1]
}解题思路
每间房选偷或不偷:
- 偷:dp[i] = dp[i-2] + nums[i](前一间不能偷)
- 不偷:dp[i] = dp[i-1](金额和前一间一样)
dp[i] = max(dp[i-1], dp[i-2] + nums[i])
和最大子数组和一样可以用滚动变量优化到 O(1) 空间,但这里 dp 依赖前两个状态(dp[i-1] 和 dp[i-2]),需要两个变量。
复杂度
- 时间:O(n)
- 空间:O(n),可优化到 O(1)