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

二刷 LeetCode:动态规划经典双题复盘

目录

一、LeetCode 1143. 最长公共子序列

题目回顾

核心思路(二维 DP)

Java 实现代码

二刷反思

二、LeetCode 72. 编辑距离

题目回顾

核心思路(二维 DP)

Java 实现代码

二刷反思

三、两道题的关联与 DP 思想总结


继续更新我的 LeetCode 二刷复盘,这次啃的是两道动态规划的经典标杆题:「最长公共子序列」和「编辑距离」。比起第一次硬套 DP 模板,这次终于把状态转移的底层逻辑给吃透了,趁热整理成博客,把关键思路和易错点沉淀下来。


一、LeetCode 1143. 最长公共子序列

题目回顾

给定两个字符串text1text2,返回这两个字符串的最长公共子序列的长度。如果不存在公共子序列,返回 0。

  • 子序列:不要求连续,只要相对顺序不变即可

核心思路(二维 DP)

这道题是双序列 DP 的入门标杆,核心是用二维 DP 表记录两个字符串前i和前j个字符的最长公共子序列长度

  • 状态定义:dp[i][j]表示text1[0..i-1]text2[0..j-1]的最长公共子序列长度
  • 状态转移方程:
    1. 如果text1[i-1] == text2[j-1]dp[i][j] = dp[i-1][j-1] + 1(当前字符匹配,子序列长度 + 1)
    2. 如果不相等:dp[i][j] = max(dp[i-1][j], dp[i][j-1])(取两个字符串分别去掉当前字符的最大值)
  • 初始化:dp[0][*] = 0dp[*][0] = 0(空字符串的公共子序列长度为 0)

Java 实现代码

java

运行

public int longestCommonSubsequence(String text1, String text2) { int m = text1.length(); int n = text2.length(); int[][] dp = new int[m + 1][n + 1]; for (int i = 1; i <= m; i++) { for (int j = 1; j <= n; j++) { if (text1.charAt(i - 1) == text2.charAt(j - 1)) { dp[i][j] = dp[i - 1][j - 1] + 1; } else { dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]); } } } return dp[m][n]; }

二刷反思

  • 第一次写的时候,只记住了转移方程,却没理解为什么要这么转移。这次才明白:不相等时取max,本质是在 **“删除 text1 当前字符” 和 “删除 text2 当前字符” 两个决策中,保留最优解 **。
  • 空间优化:可以用一维数组滚动更新,把空间复杂度从 O (mn) 降到 O (min (m,n)),核心是倒序遍历j,避免覆盖上一轮的状态。
  • 易错点:数组下标和字符串下标要区分开,dp[i][j]对应的是text1[i-1]text2[j-1],很容易写错索引。

二、LeetCode 72. 编辑距离

题目回顾

给你两个单词word1word2,请你计算出将word1转换成word2所使用的最少操作数。

  • 三种合法操作:插入一个字符、删除一个字符、替换一个字符

核心思路(二维 DP)

这道题是双序列 DP 的进阶,和「最长公共子序列」是一脉相承的,核心是用 DP 表记录将word1i个字符转为word2j个字符的最少操作数

  • 状态定义:dp[i][j]表示将word1[0..i-1]转换为word2[0..j-1]的最少操作次数
  • 状态转移方程:
    1. 如果word1[i-1] == word2[j-1]dp[i][j] = dp[i-1][j-1](字符匹配,无需操作)
    2. 如果不相等:dp[i][j] = min(dp[i-1][j], dp[i][j-1], dp[i-1][j-1]) + 1,分别对应:
      • dp[i-1][j] + 1:删除word1的当前字符
      • dp[i][j-1] + 1:在word1中插入一个字符(等价于删除word2的当前字符)
      • dp[i-1][j-1] + 1:替换word1的当前字符为word2的当前字符
  • 初始化:
    • dp[0][j] = j:空字符串转为word2的前j个字符,需要j次插入
    • dp[i][0] = iword1的前i个字符转为空字符串,需要i次删除

Java 实现代码

java

运行

public int minDistance(String word1, String word2) { int m = word1.length(); int n = word2.length(); int[][] dp = new int[m + 1][n + 1]; // 初始化边界 for (int i = 0; i <= m; i++) dp[i][0] = i; for (int j = 0; j <= n; j++) dp[0][j] = j; // 状态转移 for (int i = 1; i <= m; i++) { for (int j = 1; j <= n; j++) { if (word1.charAt(i - 1) == word2.charAt(j - 1)) { dp[i][j] = dp[i - 1][j - 1]; } else { dp[i][j] = Math.min(Math.min(dp[i - 1][j], dp[i][j - 1]), dp[i - 1][j - 1]) + 1; } } } return dp[m][n]; }

二刷反思

  • 第一次做的时候,很容易混淆三种操作对应的状态转移。这次才彻底理清:删除 / 插入 / 替换分别对应 DP 表中三个方向的状态,本质是从三种操作中选择代价最小的一种。
  • 空间优化:同样可以用一维数组优化,空间复杂度降到 O (min (m,n)),但需要额外变量保存dp[i-1][j-1]的值。
  • 易错点:初始化边界时,dp[i][0]dp[0][j]不能写错,否则整个 DP 表的计算都会出错。

三、两道题的关联与 DP 思想总结

这两道题看似不同,底层的 DP 逻辑高度同源:

  1. 双序列 DP 的通用模板
    • 定义二维 DP 表,状态表示两个字符串前i/j个字符的子问题解
    • 状态转移只依赖左、上、左上三个方向的状态
    • 初始化处理空字符串的边界情况
  2. 核心区别
    • 最长公共子序列:求最大值,字符匹配时 + 1,不匹配时取 max
    • 编辑距离:求最小值,字符匹配时直接继承,不匹配时取 min+1
  3. 二刷的最大收获:终于从 “套模板” 升级到了 “懂逻辑”,以后遇到类似的双序列 DP 题(比如「不同的子序列」「两个字符串的删除操作」),就能快速套用这套思路,而不是死记硬背。
http://www.jsqmd.com/news/753905/

相关文章:

  • Ponimator:基于姿态识别的实时动画生成技术解析
  • 2026 杭州 GEO 优化服务商实力榜单:五大头部品牌全维度评测与选型参考 - GEO优化
  • Java虚拟线程与Project Loom深度绑定指南:从编译期协程支持到JFR事件追踪(JDK21 GA后唯一权威路径)
  • 21st.dev:社区驱动的React组件注册中心,基于shadcn/ui与Tailwind CSS
  • 掌握MECE原则:结构化思维的核心工具与实战应用
  • 基于LangChain的AI代理系统:自动化软件开发生命周期实践
  • Pandas CSV:高效数据处理与数据可视化指南
  • 视频速度控制器:重塑数字时代的高效观看体验
  • 2026年4月新发布注塑集中供料系统指南:为何信百勒Simbler成为首选 - 2026年企业推荐榜
  • 避坑指南:手把手教你用Python复现股票软件的副图指标(MA/MACD/成交量)并解决配置文件路径报错
  • 2026提货卡小程序标杆名录:武汉家政小程序制作、武汉小程序制作、武汉小程序商城开发、武汉小程序开发、武汉微信下单小程序开发选择指南 - 优质品牌商家
  • 如何快速实现B站缓存视频转换:3个简单步骤永久保存珍贵内容
  • 【C++27 constexpr 极致优化权威指南】:20年编译器专家亲授7大突破性技巧,绕过ISO WG21未公开限制
  • 2026年第二季度:大师级小提琴/天然虎纹小提琴/意大利小提琴/成人小提琴/收藏小提琴/欧料小提琴/油性漆小提琴/选择指南 - 优质品牌商家
  • 2026年泸州中蜂产卵王实力厂家盘点:蜜源蜜蜜蜂养殖家庭农场为何备受推崇? - 2026年企业推荐榜
  • 鸣潮自动化脚本终极指南:解放双手,专注游戏乐趣
  • ADAS开发避坑指南:FCW前方碰撞预警的‘不报警’条件全解析与实战标定
  • 深入理解Mybatis
  • C# 13拦截器实战指南:如何在金融级交易服务中实现无侵入日志、熔断与权限校验(附IL织入对比基准)
  • 为 Ubuntu 上的 Claude Code 编程助手配置 Taotoken 作为后端
  • 上位机知识篇---ctags
  • ChatGLM2-6B部署翻车实录:Tesla M40驱动、CUDA、Torch版本兼容性全解析
  • Jieba分词‘开挂’指南:一键接入百度飞桨(PaddlePaddle)模型,提升NER和搜索效果
  • 对比在Taotoken平台调用不同模型生成代码的响应速度与效果体感
  • 2026年近期阿拉山口奢侈品回收优选:毅豪珠宝商行全方位解析 - 2026年企业推荐榜
  • 2026 成都 GEO 优化机构实力测评:五大领军品牌深度解析与企业选型指南 - GEO优化
  • C++ DoIP协议栈开源项目深度评测(3大主流实现对比),附可商用轻量级自研框架源码(限前200名领取)
  • C# 13模式匹配增强全解析,从null检查到嵌套解构——20年架构师压箱底实践笔记(仅限首发批次)
  • 2026 重庆 GEO 优化机构实力解析:五大头部品牌深度测评与企业选型指南 - GEO优化
  • Android ROM解包终极指南:一键提取系统文件的完整解决方案