在问 · 算法题解

198. 打家劫舍

题目描述

一条街上有一排房子,nums[i] 是第 i 间房子里的现金,均为非负整数。

你打算在一晚之内偷这些房子。相邻两间房子的防盗系统是连通的:只要同一晚有两间相邻房子被闯入,就会报警。

在不触发报警的前提下,返回能偷到的最大金额。

示例 1
输入:nums = [1,2,3,1]
输出:4

解释:偷第 1 间(1)和第 3 间(3),共 4。

示例 2
输入:nums = [2,7,9,3,1]
输出:12

解释:偷第 1、3、5 间,金额为 2 + 9 + 1 = 12。

数据范围

  • 1 <= nums.length <= 100
  • 0 <= nums[i] <= 400

解题思路

第 i 间房屋在偷与不偷之间取最大值:dp[i]=max(dp[i-1],dp[i-2]+nums[i])。

为什么正确

prev2、prev1 分别是处理到前两间和前一间时的最优金额。

复杂度分析

时间 O(n),空间 O(1)。

易错点

状态要代表“前缀最优”,不能只贪心选择当前最大房屋。

参考代码

Python、Java、C++、Go、JavaScript、TypeScript 六种语言,逻辑一致。

from typing import List

class Solution:
    def rob(self, nums: List[int]) -> int:
        prev2, prev1 = 0, 0
        for money in nums:
            prev2, prev1 = prev1, max(prev1, prev2 + money)
        return prev1

载入编辑器,自己跑一遍 →

动态规划 专题的其他题目

查看 动态规划 全部题目 →