news 2026/4/8 11:40:30

LeetCode198打家劫舍:从回溯到动态规划的优化历程

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
LeetCode198打家劫舍:从回溯到动态规划的优化历程

目录

方法 1:朴素回溯(暴力递归)

思路

Java 实现

时空复杂度

问题

方法 2:记忆化搜索(自顶向下 DP)

思路

Java 实现

时空复杂度

优化点

方法 3:自底向上的动态规划(DP 数组)

思路

Java 实现

时空复杂度

优化点

方法 4:空间优化的动态规划(双变量)

思路

Java 实现

时空复杂度

优化点

优化变迁总结


打家劫舍问题的核心是 “相邻房屋不能同时偷”,我们从暴力回溯开始,逐步优化到空间最优的动态规划,下面分步骤解析:

方法 1:朴素回溯(暴力递归)

思路

通过递归枚举每个房屋的两种选择:偷当前房屋(则只能偷前 i-2 个房屋的最大金额 + 当前金额)、不偷当前房屋(则偷前 i-1 个房屋的最大金额)。状态定义:dfs(i)表示 “考虑前 i 个房屋时的最大偷窃金额”。

Java 实现

class Solution { public int rob(int[] nums) { return dfs(nums, nums.length - 1); } // 递归计算前i个房屋的最大金额 private int dfs(int[] nums, int i) { if (i < 0) return 0; // 边界:没有房屋时金额为0 // 选择1:不偷i,取前i-1的最大;选择2:偷i,取前i-2的最大+当前金额 return Math.max(dfs(nums, i - 1), dfs(nums, i - 2) + nums[i]); } }

时空复杂度

  • 时间复杂度:O(2n)(每个房屋分 2 种选择,递归树深度为 n,总节点数是2n级)
  • 空间复杂度:O(n)(递归栈的深度为 n)

问题

存在大量重复计算:例如计算dfs(5)需要dfs(4)dfs(3),计算dfs(4)又需要dfs(3)dfs(2)dfs(3)会被多次计算,效率极低(n≥20 时就会超时)。

方法 2:记忆化搜索(自顶向下 DP)

思路

用 ** 备忘录(数组)** 存储已经计算过的dfs(i)结果,避免重复计算 —— 每次计算前先检查备忘录,若已存在结果则直接返回,否则计算后存入备忘录。

Java 实现

import java.util.Arrays; class Solution { private int[] memo; // 备忘录:存储每个i对应的最大金额 public int rob(int[] nums) { int n = nums.length; memo = new int[n]; Arrays.fill(memo, -1); // 初始化:-1表示该位置未计算(金额非负,不会和有效结果冲突) return dfs(nums, n - 1); } private int dfs(int[] nums, int i) { if (i < 0) return 0; if (memo[i] != -1) return memo[i]; // 已计算,直接返回 // 计算并存入备忘录 int res = Math.max(dfs(nums, i - 1), dfs(nums, i - 2) + nums[i]); memo[i] = res; return res; } }

时空复杂度

  • 时间复杂度:O(n)(每个 i 只计算 1 次)
  • 空间复杂度:O(n)(备忘录数组 + 递归栈)

优化点

解决了 “重复计算” 的问题,将时间复杂度从指数级降到线性,但仍依赖递归栈。

方法 3:自底向上的动态规划(DP 数组)

思路

把 “自顶向下的递归” 改成 “自底向上的迭代”,用DP 数组存储每个位置的最大金额,彻底避免递归栈。状态定义:dp[i]表示 “前 i 个房屋的最大偷窃金额”。状态转移:

  • 不偷第 i 个房屋:dp[i] = dp[i-1]
  • 偷第 i 个房屋:dp[i] = dp[i-2] + nums[i-1](nums 索引比 dp 小 1,因为 dp [0] 对应 “0 个房屋”)

Java 实现

class Solution { public int rob(int[] nums) { int n = nums.length; if (n == 0) return 0; // dp[i]:前i个房屋的最大金额(i从0到n) int[] dp = new int[n + 1]; dp[0] = 0; // 0个房屋,金额0 dp[1] = nums[0]; // 1个房屋,金额为nums[0] // 从第2个房屋开始迭代 for (int i = 2; i <= n; i++) { dp[i] = Math.max(dp[i - 1], dp[i - 2] + nums[i - 1]); } return dp[n]; } }

时空复杂度

  • 时间复杂度:O(n)(仅需遍历 1 次)
  • 空间复杂度:O(n)(DP 数组占用 n+1 空间)

优化点

用迭代替代递归,避免了递归栈溢出的风险,但空间仍依赖数组。

方法 4:空间优化的动态规划(双变量)

思路

观察状态转移:dp[i]只依赖dp[i-1]dp[i-2],因此不需要整个 DP 数组,只需用两个变量分别存储这两个依赖值即可。

Java 实现

class Solution { public int rob(int[] nums) { int f0 = 0; // 对应dp[i-2](前i-2个房屋的最大金额) int f1 = 0; // 对应dp[i-1](前i-1个房屋的最大金额) for (int x : nums) { int newF = Math.max(f1, f0 + x); // 计算当前房屋的最大金额 f0 = f1; // 更新f0为原来的f1(i-1 → i-2) f1 = newF; // 更新f1为当前的newF(i → i-1) } return f1; } }

时空复杂度

  • 时间复杂度:O(n)(遍历 1 次)
  • 空间复杂度:O(1)(仅用 2 个变量)

优化点

将空间复杂度从O(n)降到O(1),是该问题的最优空间方案。

优化变迁总结

朴素回溯(O(2^n)时间) ↓ 解决重复计算 记忆化搜索(O(n)时间,O(n)空间) ↓ 去掉递归栈,改为迭代 自底向上DP数组(O(n)时间,O(n)空间) ↓ 去掉冗余数组,用双变量替代 空间优化DP(O(n)时间,O(1)空间)

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/3/14 3:12:38

Git冲突解决实用指南

Git冲突解决实用指南 一、理解Git冲突的本质 1.1 冲突产生的原因 同一文件的不同修改&#xff1a;两个分支对同一文件的同一区域进行了不同的修改文件删除与修改冲突&#xff1a;一个分支删除了文件&#xff0c;另一个分支修改了该文件合并时版本差异&#xff1a;合并时存在…

作者头像 李华
网站建设 2026/3/28 1:23:58

烧光5000万美金,我终于不慌了

昨天看完了罗永浩访谈MiniMax创始人闫俊杰&#xff0c;整个访谈3小时50分&#xff0c;其中许多观点非常有启发&#xff0c;建议你完整看一遍。如果你确实没时间&#xff0c;至少认真看完这篇文章&#xff0c;要知道这可是AI大模型独角兽公司创始人&#xff0c;花了几千万美金烧…

作者头像 李华
网站建设 2026/4/4 20:58:52

对标MinIO!全新一代分布式文件系统诞生!

最近 MinIO 官方在 README 中正式宣布项目进入“维护模式”&#xff1a;不再接受新功能、增强或拉取请求&#xff1a;代码库仅进行维护&#xff0c;不再开发新特性。安全补丁和关键 bug 修复&#xff1a;会根据个案评估&#xff0c;但不是保证全面支持。问题和 PR 审查停止&…

作者头像 李华
网站建设 2026/4/6 9:48:09

Excalidraw教育场景应用:高校课程设计新工具

Excalidraw&#xff1a;高校课程设计的可视化协作新范式 在一次跨学院的教学研讨会上&#xff0c;三位教授围坐在虚拟会议室中——计算机系的李老师正在用鼠标在共享白板上勾勒一个知识框架&#xff0c;医学部的王老师实时添加注释&#xff0c;教育学院的张老师则输入一句“生成…

作者头像 李华
网站建设 2026/3/30 16:51:05

《从实验室到生活:Aloha机器人如何重新定义人机协作》

从实验室到生活&#xff1a;Aloha机器人如何重新定义人机协作一、Aloha 机器人的起源与核心突破&#xff08;一&#xff09;诞生背景&#xff1a;破解机器人操作的 “高端化” 困局在机器人发展的漫长历程中&#xff0c;高端硬件与复杂校准一直是横亘在广泛应用之路上的巨石。传…

作者头像 李华
网站建设 2026/3/17 20:39:30

开源无界,共筑未来!COSCon‘25 全球开源发展愿景论坛议程正式发布

中国开源年会 COSCon 是业界最具影响力的开源盛会之一&#xff0c;由开源社在 2015 年首次发起&#xff0c;2016 年正式得以命名。九年来&#xff0c;中国开源年会以其独特的中立社区定位及日益增加的影响力&#xff0c;吸引了越来越多国内外企业、高校、开源组织和社区的大力支…

作者头像 李华