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

LeetCode 72. 编辑距离:动态规划经典题解

刷LeetCode中等题时,编辑距离绝对是动态规划的经典代表作——它看似复杂,三种操作(插入、删除、替换)让人无从下手,但只要理清状态定义和转移逻辑,就能轻松破解。今天就带大家一步步拆解这道题,从题意分析到代码实现,把每一个细节讲透。

一、题目解读:到底要解决什么问题?

题目很简洁:给定两个单词word1和word2,返回将word1转换成word2所使用的最少操作数

允许的三种操作(对一个单词进行):

  • 插入一个字符:比如word1是“abc”,word2是“abdc”,可以在word1的b和c之间插入d,完成转换。

  • 删除一个字符:比如word1是“abcd”,word2是“abc”,删除word1的d即可。

  • 替换一个字符:比如word1是“abc”,word2是“adc”,将word1的b替换成d即可。

核心难点:三种操作可以任意组合,如何找到“最少步骤”?—— 动态规划的核心就是“最优子结构”,把大问题拆成小问题,逐个解决。

二、动态规划思路拆解(核心部分)

动态规划解题,关键就3步:定义dp数组、确定边界条件、推导状态转移方程。我们一步步来:

1. 定义dp数组

设word1的长度为n,word2的长度为m,定义dp[i][j]:将word1前i个字符(word1[0…i-1])转换成word2前j个字符(word2[0…j-1])所需的最少操作数。

为什么是i-1和j-1?因为dp数组的下标从0开始,而字符串的下标也从0开始,dp[0][0]表示两个空串的转换,dp[1][1]才对应两个单词的第一个字符,这样定义更直观,避免下标混乱。

2. 确定边界条件

边界情况就是“其中一个单词为空串”的场景:

  • 如果word1为空(i=0),那么要转换成word2前j个字符,只能不断插入j个字符,所以dp[0][j] = j。

  • 如果word2为空(j=0),那么要转换成空串,只能不断删除word1前i个字符,所以dp[i][0] = i。

比如dp[0][3] = 3(空串转成3个字符,插入3次),dp[2][0] = 2(2个字符转成空串,删除2次)。

3. 推导状态转移方程

这是最关键的一步,我们分两种情况讨论:word1的第i个字符(word1[i-1])和word2的第j个字符(word2[j-1])是否相等。

情况1:word1[i-1] == word2[j-1]

此时,两个字符已经匹配,不需要做任何操作,最少操作数就等于“word1前i-1个字符转word2前j-1个字符”的操作数,即:

dp[i][j] = dp[i-1][j-1]

比如word1是“abc”,word2是“adc”,当i=3、j=3时,word1[2] = c,word2[2] = c,此时dp[3][3] = dp[2][2]。

情况2:word1[i-1] != word2[j-1]

此时需要进行插入、删除、替换三种操作中的一种,取这三种操作的最少步骤即可,对应三个方向的状态:

  • 删除操作:删除word1的第i个字符,此时dp[i][j] = dp[i-1][j] + 1(删除1次,加上之前的操作数)。

  • 插入操作:在word1的第i个字符后插入一个和word2[j-1]相同的字符,此时dp[i][j] = dp[i][j-1] + 1(插入1次,加上之前的操作数)。

  • 替换操作:将word1的第i个字符替换成word2[j-1],此时dp[i][j] = dp[i-1][j-1] + 1(替换1次,加上之前的操作数)。

所以,状态转移方程为:

dp[i][j] = Math.min(dp[i-1][j] + 1, dp[i][j-1] + 1, dp[i-1][j-1] + 1)

三、完整代码实现(TypeScript)

结合上面的思路,直接上代码,每一行都加了详细注释,对应我们拆解的逻辑:

functionminDistance(word1:string,word2:string):number{letn=word1.length;// word1的长度letm=word2.length;// word2的长度// 边界情况:有一个字符串为空串,操作数就是另一个字符串的长度if(n*m==0){returnn+m;}// 初始化dp数组:n+1行(word1的0~n个字符),m+1列(word2的0~m个字符)constdp:number[][]=Array.from({length:n+1},()=>newArray(m+1));// 边界状态初始化:word2为空时,dp[i][0] = i(删除i次)for(leti=0;i<n+1;i++){dp[i][0]=i;}// 边界状态初始化:word1为空时,dp[0][j] = j(插入j次)for(letj=0;j<m+1;j++){dp[0][j]=j;}// 填充dp数组:遍历所有i和j,计算每个dp[i][j]的值for(leti=1;i<n+1;i++){for(letj=1;j<m+1;j++){// 左:删除操作,dp[i-1][j] + 1letleft=dp[i-1][j]+1;// 下:插入操作,dp[i][j-1] + 1letdown=dp[i][j-1]+1;// 左下:替换/不操作,先取dp[i-1][j-1]letleft_down=dp[i-1][j-1];// 字符不相等时,替换操作需要+1if(word1.charAt(i-1)!=word2.charAt(j-1)){left_down+=1;}// 取三种操作的最小值,赋值给dp[i][j]dp[i][j]=Math.min(left,Math.min(down,left_down));}}// dp[n][m]就是word1完整转word2的最少操作数returndp[n][m];};

四、代码解析与易错点提醒

1. 易错点1:边界条件的判断

当n*m == 0时,说明其中一个字符串长度为0,此时直接返回n+m即可,不用再初始化dp数组,节省时间。比如word1为空,word2长度为5,返回5(插入5次)。

2. 易错点2:dp数组的初始化

dp数组的长度是n+1和m+1,因为要包含“0个字符”的情况,比如dp[0][0] = 0(两个空串,无需操作)。

3. 易错点3:字符串下标与dp数组下标的对应

dp[i][j]对应word1[0…i-1]和word2[0…j-1],所以取字符时要用word1.charAt(i-1)和word2.charAt(j-1),千万别写成i和j,否则会越界。

五、总结:这道题的核心价值

编辑距离是动态规划的经典应用,它的核心思想是“用子问题的最优解推导原问题的最优解”。这道题的关键不是记住代码,而是理解:

  • 如何定义dp数组,让它能表示“子问题的最优解”;

  • 如何根据题意,找到边界条件(极端情况);

  • 如何分析不同场景,推导状态转移方程。

学会这道题后,再遇到类似的“最少操作”“最优路径”类动态规划题,思路会清晰很多。比如字符串匹配、最长公共子序列等,都能用到类似的思维。

http://www.jsqmd.com/news/752697/

相关文章:

  • 深入探索水下机器人仿真:专业级ROS平台实战指南
  • 三步解决B站直播弹幕显示难题:BLiveChat让OBS互动更专业
  • Translumo屏幕实时翻译工具终极指南:5分钟掌握高效跨语言沟通技巧
  • PhysMaster:基于强化学习的物理合理视频生成技术解析
  • 体验Taotoken多模型聚合路由带来的服务稳定性提升
  • 别再只用WebRTC了!用LiveKit Server + Go 手把手搭建一个低延迟的Web音视频聊天室
  • 基于Logistic98/chatgpt-fine-tuning项目的GPT模型微调实战指南
  • 保姆级教程:用VMware Workstation 17在Windows电脑上体验macOS Monterey(附AMD CPU避坑配置)
  • Apollo Save Tool:终极PS4存档管理解决方案,轻松备份和修改游戏进度
  • 如何在3分钟内为Windows 11 LTSC系统安装微软商店:终极完整指南
  • 微信Dat文件的前世今生:从异或加密到WxDatViewer,聊聊数据安全与隐私保护
  • CH582单片机SysTick定时器实战:1秒精准闪烁LED(附串口打印调试技巧)
  • MySQL执行计划优化 = 加索引?
  • 告别纸上谈兵:在浏览器里用MARIE.js写你的第一个汇编程序(含完整代码)
  • 2026届学术党必备的五大AI辅助论文网站推荐
  • Masa Mods汉化资源包:让Minecraft模组界面彻底说中文的完整指南
  • python学习Day12:pandas安装与实际运用
  • 你的手机Wi-Fi跑不满?可能是这3个‘隐形杀手’在作怪(附手机/电脑自查指南)
  • 告别低价陷阱!扬中金展母线槽,工程性价比之选
  • 如何利用Grok 4.3辅助Python编程:完整方法论与高阶提示词库(2026国内开发者实战指南)
  • 抖音视频怎么无水印保存到相册?抖音无水印保存教程2026最新实测全攻略 - 爱上科技热点
  • 豆包视频怎么去水印?豆包视频去水印方法全测评,2026最新 亲测有效 - 爱上科技热点
  • 无人机 大疆 极飞添加自定义高清地图源教程
  • 告别重复介绍!你的专属AI伙伴终于来了
  • 北斗导航 | 基于麻雀搜索算法的接收机自主完好性监测(RAIM)算法研究
  • 机器人算法评估系统:提升测试效率与准确性的关键技术
  • 高并发场景下 JWT 签名验证怎么优化减少 CPU 占用?
  • 实战避坑:在Matlab中实现CA-CFAR时,我的参考单元和护卫单元到底怎么设?
  • 抖音视频怎么无水印保存到相册?抖音视频无水印保存方法 2026最新 实测全攻略 - 爱上科技热点
  • 别只盯着野指针!GD32/HC32单片机卡死在0xFFFFFFFE,这个SystemInit里的坑你踩过吗?