打家劫舍算法:动态规划思路与实现解析

打家劫舍算法:动态规划思路与实现解析

在这里插入图片描述

在算法的世界里,“打家劫舍”是一道经典的动态规划题目,它以巧妙的逻辑和实用的场景,让我们能深入体会动态规划思想如何解决实际问题。接下来,我们将全面剖析这一算法,从解题思路梳理,到代码实现,再到对算法结构和优点的解读,带你掌握解决这类问题的关键 。

一、题目理解与需求分析

(一)题目描述

你是个专业小偷,计划偷窃沿街房屋,每间房有一定现金。但相邻房屋装有防盗系统,若相邻房屋同一晚被闯入就会报警。给定代表每个房屋现金金额的非负整数数组,要计算不触动警报时,一夜能偷窃到的最高金额。比如数组 [1,2,3,1] ,最高金额是 4(偷第 1、3 间房 );数组 [2,7,9,3,1] ,最高金额是 12(偷第 1、3、5 间房 ) 。

(二)核心矛盾提炼

  • 选择矛盾:对于每个房屋,有两种选择——偷或者不偷。但如果偷当前房屋,就不能偷相邻的前一个房屋;如果不偷,那最高金额就取决于前面房屋能偷到的最高值。
  • 最优子结构:整个问题的最优解(偷完所有房屋能得到的最高金额 ),依赖于其子问题的最优解(前 n - 1 个房屋、前 n - 2 个房屋等能偷到的最高金额 )。

二、解题思路:动态规划的应用

(一)状态定义

我们定义 dp[i] 表示偷窃到第 i 个房屋时,能得到的最高金额。这样就把原问题拆解成了一个个子问题,通过求解子问题的最优解来得到原问题的最优解。

(二)状态转移方程推导

对于第 i 个房屋,有两种情况:

  • 偷第 i 个房屋:那么第 i - 1 个房屋就不能偷,此时最高金额是 dp[i - 2] + nums[i]dp[i - 2] 是前 i - 2 个房屋能偷到的最高金额,加上当前房屋的金额 nums[i] )。
  • 不偷第 i 个房屋:此时最高金额就等于 dp[i - 1](即前 i - 1 个房屋能偷到的最高金额 )。

所以,状态转移方程为:dp[i] = max(dp[i - 1], dp[i - 2] + nums[i])

(三)初始条件确定

  • 当只有 1 个房屋(i = 0 )时,显然 dp[0] = nums[0] ,因为只能偷这一个房屋。
  • 当有 2 个房屋(i = 1 )时,要选金额较大的那个房屋偷,所以 dp[1] = max(nums[0], nums[1])

(四)遍历求解

从前往后遍历房屋数组,根据状态转移方程依次计算 dp[i] 的值,直到遍历完所有房屋,最后 dp[n - 1]n 是房屋数量 )就是我们要求的最高金额。

举个简单例子,看数组 [1,2,3,1]

  1. 初始化 dp[0] = 1dp[1] = max(1, 2) = 2
  2. 计算 i = 2(对应金额 3 )时,dp[2] = max(dp[1], dp[0] + 3) = max(2, 1 + 3) = 4
  3. 计算 i = 3(对应金额 1 )时,dp[3] = max(dp[2], dp[1] + 1) = max(4, 2 + 1) = 4 。最终得到最高金额是 4 ,和题目示例结果一致。

三、代码示例(Python 实现)

def rob(nums):
    n = len
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

哲谐嘉xhm

您的赞赏是我创作的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值