持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第3天,点击查看活动详情
今天我们来做一下leetcode上面的一道比较经典字符串类动态规划题目 72. 编辑距离
题意
题意比较简单,给我们两个字符串word1和word2,让我们求从word1转换成word2的最小次数,转换的操作可以有三种
- 向word1中插入一个字符
- 将word1中一个字符删除
- 替换word1中的一个字符为另外一个
像我一样初次接触动态规划的同学,我推荐一个理解动规类题目思路的方法,可能不是很实用,但是很有效。
那就是我们拿一支笔、一张纸手动画出递推的表格,手动模拟一次完整的递推过程,当我们弄明白大概的递推过程之后,对于我们理解边界情况和后续的代码编写都会有很大的好处。
相信做过一些动态规划类题目的同学,尤其是字符串类动态规划,会发现其中的一些套路,这道题也不例外。
别看题目的标签打的是困难,但是实际难度比另外一道同样的字符串DP的题目剑指 Offer 19. 正则表达式匹配难度小很多
思路
既然是要使用动规进行解答,那么就少不了分析其中的递推过程,也就是我们可以从最简单的情况开始考虑,根据递推 关系解出更大规模的问题。 例如 word1=horse word2 = ros 记:m = word1.length,n = words2.length
-
状态定义 dp[i][j]表示word1前i个字符变成word2前j个字符的最小操作数
-
状态初始化
- 假设word1为空,那么word1变成word2的操作只能是新增,具体的操作数应该等同于word2中的字符数
- 具体代码如下
dp[0][j] = jj的范围是[0-n]
- 具体代码如下
- 同样,假设word2为空,那么word1变成word2的操作只能删除,具体的操作数应该等于word1的字符数
- 具体代码如下
dp[i][0] = ii的范围是[0-m]
- 具体代码如下
- 假设word1为空,那么word1变成word2的操作只能是新增,具体的操作数应该等同于word2中的字符数
-
状态转移方程
- 考虑word1的前i位如何变成word2的前i位时,需要看最后一位是否相同,即word1[i-1] word2[j-1]
- 如果word1[i-1]==word2[j-1] 那么dp[i][j] = dp[i-1][j-1]
- 如果不同的话,考虑不同的编辑方式
- 如果替换,dp[i][j] = dp[i-1][j-1] + 1
- 如果删除,即删除word1的最后一个字符,那么有 dp[i][j] = dp[i-1][j] + 1
- 如果新增,即新增word2的最后一个字符,那么有 dp[i][j] = dp[i][j-1] + 1
- 最终的结果取三者的最小值
- 考虑word1的前i位如何变成word2的前i位时,需要看最后一位是否相同,即word1[i-1] word2[j-1]
至此,我们就分析完了这道题目
代码实现
结束语
如果有更好的分析思路,欢迎大家在评论区发表看法!⛄