【附源码】Python :打家劫舍

系列文章目录

Python 算法学习:打家劫舍问题


文章目录


一、算法需求

"打家劫舍"问题是一个经典的动态规划问题,通常用来描述一个小偷在一条街上偷窃房屋的场景。每间房屋都有一定数量的现金,小偷需要决定偷哪些房屋以最大化他的收益。但是,小偷面临一个限制:如果两间相邻的房屋在同一晚上被偷,那么防盗系统会触发报警。因此,小偷不能偷窃相邻的房屋。


二、解题思路

动态规划: 定义一个数组 dp,其中 dpi 表示到第 i 间房屋为止能偷到的最大金额。状态转移方程是 dpi = max(dpi-1, dpi-2 + numsi),表示可以选择偷当前房子(前提是不偷前一个房子)或者不偷当前房子(延续前一个房子的决策)。

贪心算法: 虽然不总是最优,但可以作为一种尝试。在每一步选择当前能获得的最大金额,而不考虑未来的房子。

递归: 通过递归函数模拟决策过程,考虑偷或不偷当前房子,并取两种选择中的最大值。

优化空间: 使用两个变量代替数组,减少空间复杂度。


三、具体方法+源码

方法1:动态规划(自底向上)

状态定义:dpi 表示到第 i 个房子为止能偷到的最大金额。

计算过程:

dp0 = 2(只考虑第一个房子)

dp1 = max(2, 7) = 7(考虑第一个和第二个房子)

dp2 = max(7, 2+9) = 9(考虑第二个和第三个房子)

dp3 = max(9, 7+3) = 10(考虑第三个和第四个房子)

dp4 = max(10, 9+1) = 12(考虑第四个和第五个房子)

结果:12

代码如下:

python 复制代码
def rob1(nums):
    if not nums:
        return 0
    if len(nums) == 1:
        return nums[0]
    dp = [0] * len(nums)
    dp[0] = nums[0]
    dp[1] = max(nums[0], nums[1])
    for i in range(2, len(nums)):
        dp[i] = max(dp[i-1], dp[i-2] + nums[i])
    return dp[-1]

# 测试
nums = [2, 7, 9, 3, 1]
print("最高金额:", rob1(nums))

方法2:动态规划(自顶向下)

计算过程:

从 rob(0) 开始

rob(1) = max(rob(2), rob(3)) = max(7, 9) = 9

rob(2) = max(rob(3), rob(4) + 2) = max(9, 10) = 10

rob(3) = max(rob(4), rob(5) + 3) = max(9, 12) = 12

rob(4) = max(rob(5), rob(6) + 1) = max(7, 12) = 12

结果:12

代码如下:

python 复制代码
def rob2(nums):
    memo = {}
    def rob(i):
        if i >= len(nums):
            return 0
        if i in memo:
            return memo[i]
        memo[i] = max(rob(i+1), nums[i] + rob(i+2))
        return memo[i]
    return rob(0)

# 测试
nums = [2, 7, 9, 3, 1]
print("最高金额:", rob2(nums))

方法3:优化的动态规划

计算过程:

prev = 2, curr = 7

prev = 7, curr = 9

prev = 9, curr = 10

prev = 10, curr = 12

结果:12

代码如下:

python 复制代码
def rob3(nums):
    if not nums:
        return 0
    if len(nums) == 1:
        return nums[0]
    prev, curr = 0, 0
    for num in nums:
        prev, curr = curr, max(prev + num, curr)
    return curr

# 测试
nums = [2, 7, 9, 3, 1]
print("最高金额:", rob3(nums))

方法4:递归

计算过程:

helper(0) = max(helper(1), helper(2) + 2) = max(7, 9) = 9

helper(1) = max(helper(2), helper(3) + 7) = max(9, 10) = 10

helper(2) = max(helper(3), helper(4) + 9) = max(10, 12) = 12

helper(3) = max(helper(4), helper(5) + 3) = max(9, 12) = 12

helper(4) = max(helper(5), 1) = 12

结果:12

代码如下:

python 复制代码
def rob4(nums):
    def helper(i):
        if i == len(nums):
            return 0
        if i == len(nums) - 1:
            return nums[i]
        return max(helper(i+1), nums[i] + helper(i+2))
    return helper(0)

# 测试
nums = [2, 7, 9, 3, 1]
print("最高金额:", rob4(nums))

总结

这个问题在算法学习中非常重要,因为它展示了如何使用动态规划解决具有重叠子问题和最优子结构特性的问题。它也常用于面试中,考察候选人对动态规划的理解和应用能力。

这个问题的变种也很多,比如考虑环形街道的情况,或者房屋之间的防盗系统有不同的触发条件等。

相关推荐
jufeng13071 小时前
【系列:手搓自主 AI Agent:Hermes 架构原理剖析 · 第 11 篇】
python·ai agent·mcp
mqiqe1 小时前
AgentScope Java Harness:4. 双层记忆系统 让 Agent 拥有真正的“长期大脑“
java·开发语言
gugucoding1 小时前
46. 【Java】JUC并发工具:让并发更简单
java·开发语言
En^_^Joy1 小时前
Django项目配置全攻略:settings配置文件
后端·python·django
Nebula_g2 小时前
JavaSE基础语法:面向对象高级(代码中的成分)
java·开发语言·编程·javase·技术栈·高级语法
for_ever_love__2 小时前
python基础语法学习: 异常的传递性
开发语言·python·学习
AC赳赳老秦3 小时前
公开图片 OCR 数据提取:OpenClaw 合规采集公开信息图,识别文字与表格并转化为结构化数据
java·大数据·前端·数据库·python·php·openclaw
依然鸣3 小时前
PTA团体程序设计天梯赛L1真题讲解L1-077-080
开发语言·c++·算法·深度优先·pat考试·图论
byxdaz3 小时前
QT中服务使用
开发语言·qt