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

动态规划实战:打家劫舍系列全解析

一、题型整体分析

打家劫舍系列核心规则:不能偷窃相邻房屋,求能获取的最大金额。 属于典型一维线性 DP,在斐波那契递推逻辑上增加条件判断,分三个主流版本:基础版、环形房屋、树形房屋。

DP 通用四步法依旧适用:状态定义 → 初始化 → 状态转移 → 结果输出

二、版本 1:基础打家劫舍(LeetCode 198)

题目描述

给定一维数组,每个元素代表房屋金额,相邻房屋不能同时偷窃,求偷窃的最大总金额。

步骤推导

  1. 状态定义dp[i]:偷窃前i间房屋能得到的最大金额
  2. 状态转移方程
  • 偷第i间:则第i-1间不能偷,总金额 =dp[i-2] + nums[i-1]
  • 不偷第i间:总金额 =dp[i-1]
  • 最终取两者最大值:dp[i] = max(dp[i-1], dp[i-2] + nums[i-1])
  1. 初始边界
  • dp[0] = 0:无房屋,金额为 0
  • dp[1] = nums[0]:只有一间房,直接偷它

完整代码(DP 数组版)

#include <iostream> #include <vector> #include <algorithm> using namespace std; int rob(vector<int>& nums) { int n = nums.size(); if(n == 0) return 0; if(n == 1) return nums[0]; vector<int> dp(n + 1); dp[0] = 0; dp[1] = nums[0]; for(int i = 2; i <= n; ++i) { dp[i] = max(dp[i-1], dp[i-2] + nums[i-1]); } return dp[n]; }

空间优化版(O (1) 空间)

仅依赖前两个状态,用变量替代数组,刷题首选:

int robOpt(vector<int>& nums) { int n = nums.size(); if(n == 0) return 0; if(n == 1) return nums[0]; int pre2 = 0; // dp[i-2] int pre1 = nums[0]; // dp[i-1] int cur = 0; for(int i = 1; i < n; ++i) { cur = max(pre1, pre2 + nums[i]); pre2 = pre1; pre1 = cur; } return pre1; }

三、版本 2:环形房屋(LeetCode 213)

题目变化

房屋围成环形,第一间和最后一间也视为相邻,不能同时偷窃。

解题思路

环形问题拆解为两个线性子问题,取最大值:

  1. 不偷第一间:偷窃范围nums[1] ~ nums[n-1]
  2. 不偷最后一间:偷窃范围nums[0] ~ nums[n-2]复用基础版代码,分别计算两个区间结果,返回较大值。

完整代码

// 复用基础版逻辑,指定左右区间 int robRange(vector<int>& nums, int l, int r) { int pre2 = 0, pre1 = 0, cur = 0; for(int i = l; i <= r; ++i) { cur = max(pre1, pre2 + nums[i]); pre2 = pre1; pre1 = cur; } return pre1; } int robCircle(vector<int>& nums) { int n = nums.size(); if(n == 0) return 0; if(n == 1) return nums[0]; // 两种情况取最大 return max(robRange(nums, 0, n-2), robRange(nums, 1, n-1)); }

四、版本 3:二叉树房屋(LeetCode 337)

题目变化

房屋以二叉树形式排列,不能偷窃父子节点,求最大金额。 结合二叉树 + 动态规划 + 递归,属于树形 DP 入门。

状态定义(每个节点维护两个状态)

  1. dp[0]:不偷当前节点,子节点可偷 / 可不偷,取最大值
  2. dp[1]:偷当前节点,左右子节点都不能偷

状态转移

  • 偷当前节点:dp[1] = root->val + left[0] + right[0]
  • 不偷当前节点:dp[0] = max(left[0], left[1]) + max(right[0], right[1])

完整代码

struct TreeNode { int val; TreeNode* left; TreeNode* right; TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} }; // 返回数组:[不偷当前节点最大值, 偷当前节点最大值] vector<int> dfs(TreeNode* root) { if(!root) return {0, 0}; vector<int> left = dfs(root->left); vector<int> right = dfs(root->right); // 偷当前节点 int robCur = root->val + left[0] + right[0]; // 不偷当前节点 int notRobCur = max(left[0], left[1]) + max(right[0], right[1]); return {notRobCur, robCur}; } int robTree(TreeNode* root) { vector<int> res = dfs(root); return max(res[0], res[1]); }

五、三类题型核心对比

表格

题型特点解题核心
线性房屋首尾不相邻基础一维 DP,相邻不能选
环形房屋首尾相邻拆分为两个线性区间,取最大值
树形房屋父子节点相邻树形 DP,每个节点维护「偷 / 不偷」双状态

六、一维 DP 通用优化技巧

  1. 状态仅依赖前 1~2 项 → 用滚动变量替换数组,空间从 O (n) 降至 O (1)
  2. 环形结构 → 拆分线性区间,化环为链
  3. 树形结构 → 后序递归遍历,每个节点记录多状态

七、新手易错点

  1. 环形房屋忽略首尾相邻规则,直接套用基础代码
  2. 边界判断缺失(数组为空、只有单个元素)导致运行错误
  3. 树形 DP 混淆「偷 / 不偷」两个状态的转移逻辑
  4. 空间优化时,变量更新顺序颠倒

八、今日总结

  1. 打家劫舍是一维 DP 经典系列,核心约束:相邻元素互斥选择
  2. 线性版掌握基础转移方程,环形版学会拆环成链
  3. 树形版入门树形 DP,理解一个节点维护多个状态的思想
  4. 优先掌握空间优化写法,笔试面试更占优势
http://www.rkmt.cn/news/1424046.html

相关文章:

  • H3CSE 高性能园区网:NQA 网络质量分析详解
  • android跨应用截屏方案
  • Lumerical FDTD自动化脚本入门:从环境配置到第一个仿真循环(Python 3.11实测)
  • 从《超级马里奥》到你的游戏:用Unity Tilemap复刻经典FC关卡,并加入你自己的创意
  • 基于RAG与智能调度的个性化AI新闻聚合系统实践
  • Matlab Simulink中可直接运行的八字路径MPC车辆跟踪仿真(带中文注释+操作录像)
  • Android Studio入门实战:含登录注册、MD5密码保护与SQLite增删改查的学生管理系统源码
  • 论文格式改到凌晨?okbiye 智能排版实测,10 分钟搞定高校专属格式规范
  • ComfyUI-Easy-Use Get/Set节点终极修复指南:三步解决数据传递难题
  • 深入 Android 底层开发:JNI 注册机制、SO 库加载原理与安全防护策略
  • 3个实战技巧:彻底掌握ThinkPad风扇控制的静音与性能平衡
  • VSCode Mermaid插件:技术文档图表化的专业解决方案
  • Java 核心进阶:从异常处理到常用工具类
  • GitHub开源项目日报 · 2026年5月27日 · AI技能框架爆发,工具链生态成焦点
  • Claude画像标签体系崩塌前夜:3大信号预示模型老化,附72小时内紧急修复SOP(含Python自动化诊断脚本)
  • 3步解锁鸣潮自动化神器:告别重复刷本的终极方案
  • Spring Boot+Vue智慧校园系统源码包:含数据库脚本、架构图、部署文档与28张功能截图
  • WaveTools深度解析:3分钟彻底解决鸣潮120帧解锁失效问题
  • DIY热成像微距适配器:低成本实现PCB故障精准定位
  • AI写论文超实用!4款AI论文写作工具,解决写论文的烦恼!
  • 老Acer笔记本装Ubuntu 20.04,WiFi驱动折腾记(附Acer-wmi禁用与NetworkManager修复)
  • 大厂UR组锁岗内幕:为什么秋招第一周投递的回复率是后期的十倍?「蒸汽求职分享」
  • Lindy智能招聘模块响应延迟超8秒?性能压测报告曝光:92%企业忽略的3层缓存穿透陷阱
  • CVE-2026-5426深度解析:KnowledgeDeliver硬编码密钥零日漏洞与Godzilla+Cobalt Strike完整攻击链实战还原
  • 数字信任重构:AI、区块链与未来媒体的信任三角解析
  • 小米初代扫地机器人STM32F103+FreeRTOS完整可运行工程(含驱动、协议、任务调度)
  • 从零构建LoFi无线电:Arduino与AM/FM收音机DIY实战指南
  • 大学生怎么进 AI 智能体这个行业?我问了几个已经入行的人
  • 2026年矿用开关柜厂家推荐排行榜:乐清、贵阳、新疆、甘肃、温州等产地防爆配电柜/馈电柜/起动箱/矿用一般型开关柜实力品牌解析 - 品牌企业推荐师(官方)
  • 带GUI的人脸识别小工具:Python+TensorFlow实现检测、对齐、特征提取与身份匹配全流程