LeetCode 0198-打家劫舍

说明

你是一个专业的小偷, 计划偷窃沿街的房屋. 每间房内都藏有一定的现金, 影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统, 如果两间相邻的房屋在同一晚上被小偷闯入, 系统会自动报警.

给定一个代表每个房屋存放金额的非负整数数组, 计算你 不触动警报装置的情况下, 一夜之内能够偷窃到的最高金额.

示例

输入:[1,2,3,1]
输出:4
解释:偷窃 1 号房屋 (金额 = 1), 然后偷窃 3 号房屋 (金额 = 3). 
     偷窃到的最高金额 = 1 + 3 = 4 . 

输入:[2,7,9,3,1]
输出:12
解释:偷窃 1 号房屋 (金额 = 2), 偷窃 3 号房屋 (金额 = 9), 接着偷窃 5 号房屋 (金额 = 1). 
     偷窃到的最高金额 = 2 + 9 + 1 = 12. 

解1 动态规划

思路

以[1,2,3,1]为例:

  • 当n=1时, 最大值为 nums[0]
  • 当n=2时, 最大值为 max(nums[0], nums[1])
  • 当n=3时, 最大值为 max(nums[0]+nums[2], nums[1])
  1. 状态定义: 设动态规划矩阵 d p dp dp, d p [ i ] dp[i] dp[i]代表从索引 i 位置上的最大金额
  2. 转移方程:
  • 当i=0, dp[0] = nums[0]
  • 当i=1, dp[1] = max(nums[0], nums[1])
  • 当i=2, dp[2] = max(dp[1], dp[0]+nums[2])
  • 当i=k, dp[k] = max(dp[k-1], dp[k-2]+nums[k])
  1. 初始状态: dp[0] = nums[0], dp[1] = max(nums[0], nums[1])
  2. 返回值: dp[-1]

复杂度

  1. 时间复杂度 O ( N ) O(N) O(N)
  2. 空间复杂度 O ( N ) O(N) O(N)
class Solution:
    def rob(self, nums: List[int]) -> int:
        if not nums:
            return 0
        n = len(nums)
        dp = [0] * n
        if n == 1:
            return nums[0]
        dp[0] = nums[0]
        dp[1] = max(nums[0], nums[1])
        for i in range(2, n):
            dp[i] = max(nums[i] + dp[i - 2], dp[i - 1])
        return dp[-1]

解2 动态规划

思路

用dp1和dp2两个变量, 分别保存以下两个值:

  • dp1 当前位置的前一位能够取到的最大金额
  • dp2 当前位置能够取到的最大金额

复杂度

  1. 时间复杂度 O ( N ) O(N) O(N)
  2. 空间复杂度 O ( 1 ) O(1) O(1)
class Solution:
    def rob(self, nums: List[int]) -> int:
        if not nums:
            return 0
        n = len(nums)
        if n == 1:
            return nums[0]
        elif n == 2:
            return max(nums[0], nums[1])
        dp1, dp2 = nums[0], max(nums[0], nums[1])
        for i in range(2, len(nums)):
            dp1, dp2 = dp2, max(dp2, nums[i] + dp1)
        return dp2
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值