当前位置: 首页 > ops >正文

动态规划题解_打家劫舍【LeetCode】

198. 打家劫舍

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

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

示例 1:

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

示例 2:

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

这个问题的核心思想是动态规划。我们可以将问题分解为子问题:

  • 对于每个房子 i,我们有两种选择:偷或不偷。
  • 如果我们偷了第 i 个房子,那么我们不能偷第 i-1 个房子,所以最大金额是 dfs(i - 2) + nums[i]
  • 如果我们不偷第 i 个房子,那么最大金额是 dfs(i - 1)
  • 我们取这两种选择中的最大值作为 dfs(i) 的结果。

 下面关于这道题目的具体题解,思路和之前的爬楼梯题目解题思路一致,建议先看完这篇文档再来继续食用哦~~

动态规划题解——爬楼梯【LeetCode】三种方法_动态规划 爬楼梯-CSDN博客


一、算法逻辑(每一步思路)

❓ 问题描述:

给定一个整数数组 nums,每个元素表示某一间房屋中的金额。相邻的房屋不能被同时偷盗,问最多可以偷多少钱


✅ 解题思路(DP 状态定义与转移)

1. 状态定义:

设:

  • f0 表示「不偷当前这家时的最大收益」;
  • f1 表示「偷当前这家时的最大收益」。

随着遍历每一间房,我们动态更新这两个变量。

2. 状态转移逻辑:

对于当前房屋金额 x

  • 如果我们它,就不能偷上一个:f1 = f0 + x
  • 如果我们不偷它,就保留上一个偷的最大值:f1 = max(f1, f0 + x)
  • 所以前一步状态要滚动更新:先将 f0 = f1,然后用前一个 f0 + x 计算新的 f1

总结起来为:

f0, f1 = f1, max(f1, f0 + x)
3. 初始化:
  • 初始时 f0 = f1 = 0,表示没偷任何房屋;
  • 随着每个房间的遍历进行动态更新。
4. 最终返回结果:
  • f1 就是最终的最大收益(在遍历结束后,无论最后一间偷还是不偷都已被计算)。

二、算法核心点

✅ 核心思想:动态规划 + 状态滚动

  • 对于每一间房子都有两种选择:偷或不偷
  • 关键是不能偷相邻的两家,因此形成状态递推结构;
  • 用两个变量 f0f1 取代整个数组,进行滚动优化
class Solution:def rob(self, nums: List[int]) -> int:f0 = f1 = 0for x in nums:f0, f1 = f1, max(f1, f0 + x)return f1

三、复杂度分析

  • 时间复杂度:O(n)
    • 遍历数组一遍。
  • 空间复杂度:O(1)
    • 只用了两个变量(而不是数组),空间极致优化。

总结表

维度

内容

✅ 思路逻辑

每间房子选择“偷”或“不偷”,根据前一个状态递推最大金额

✅ 核心技巧

动态规划 + 状态滚动优化(用 f0, f1 代替 dp 数组)

✅ 时间复杂度

O(n)

✅ 空间复杂度

O(1)


✅ 举个例子说明

输入:

nums = [2, 7, 9, 3, 1]

状态变化:

初始: f0 = 0, f1 = 0
遍历 2: f0 = 0, f1 = max(0, 0 + 2) = 2
遍历 7: f0 = 2, f1 = max(2, 0 + 7) = 7
遍历 9: f0 = 7, f1 = max(7, 2 + 9) = 11
遍历 3: f0 = 11, f1 = max(11, 7 + 3) = 11
遍历 1: f0 = 11, f1 = max(11, 11 + 1) = 12

最终返回 f1 = 12

http://www.xdnf.cn/news/15470.html

相关文章:

  • 解决容器dns问题
  • [时序数据库-iotdb]时序数据库iotdb的安装部署
  • Go从入门到精通(25) - 一个简单web项目-实现链路跟踪
  • audiorecord 之 抢占优先级
  • 数据库询问RAG框架Vanna的总体架构
  • CMake基础:覆盖项目开发的五大配套工具
  • 数据结构——顺序表的相关操作
  • 信息学奥赛一本通 1552:【例 1】点的距离
  • 【Keil】C/C++混合编程的简单方法
  • 内存的基础相关知识,什么是内存,内存管理
  • 学习C++、QT---26(QT中实现记事本项目实现文件路径的提示、C++类模板、记事本的行高亮的操作的讲解)
  • LVS(Linux Virtual Server)详细笔记(理论篇)
  • 202507中央城市工作会议
  • 【Java】JUC并发(线程的方法、多线程的同步并发)
  • UE5多人MOBA+GAS 23、制作一个地面轰炸的技能
  • SHAP 值的数值尺度
  • 梳理Bean的创建流程
  • burpsuite使用中遇到的一些问题(bp启动后浏览器无法连接)/如何导入证书
  • GPIO 输入/输出
  • 2025年睿抗机器人开发者大赛CAIP-编程技能赛-高职组(省赛)解题报告 | 珂学家
  • 在Autodl服务器中使用VNC建立图形界面
  • 快速排序:原理、示例与 C 语言实现详解
  • C语言---自定义类型(下)(枚举和联合类型)
  • 云服务器如何管理数据库(MySQL/MongoDB)?
  • 【html常见页面布局】
  • 50天50个小项目 (Vue3 + Tailwindcss V4) ✨ | DoubleClickHeart(双击爱心)
  • netstat -tlnp | grep 5000
  • Swift实现股票图:从基础到高级
  • python的形成性考核管理系统
  • 并发-原子变量类