0
点赞
收藏
分享

微信扫一扫

LeetCode072之编辑距离(相关话题:动态规划)


题目描述:

给你两个单词 word1 和 word2, 请返回将 word1 转换成 word2 所使用的最少操作数  。

你可以对一个单词进行如下三种操作:

插入一个字符
删除一个字符
替换一个字符
 

示例 1:

输入:word1 = "horse", word2 = "ros"
输出:3
解释:
horse -> rorse (将 'h' 替换为 'r')
rorse -> rose (删除 'r')
rose -> ros (删除 'e')

示例 2:

输入:word1 = "intention", word2 = "execution"
输出:5
解释:
intention -> inention (删除 't')
inention -> enention (将 'i' 替换为 'e')
enention -> exention (将 'n' 替换为 'x')
exention -> exection (将 'n' 替换为 'c')
exection -> execution (插入 'u')

解题思路:

对单词 A 删除一个字符和对单词 B 插入一个字符是等价的。

同理,对单词 B 删除一个字符和对单词 A 插入一个字符也是等价的;

对单词 A 替换一个字符和对单词 B 替换一个字符是等价的。


这样以来,本质不同的操作实际上只有三种:

在单词 A 中插入一个字符;

在单词 B 中插入一个字符;

修改单词 A 的一个字符。

上面这个结论对实际解题意义不大但是引出一种重要的解题思想:

把原问题转化为规模较小的子问题

重点看下面动态规划的表格:

LeetCode072之编辑距离(相关话题:动态规划)_动态规划

第一行,是 ​​word1​​​ 为空变成 ​​word2​​ 最少步数,就是插入操作

第一列,是 ​​word2​​ 为空,需要的最少步数,就是删除操作

用 dp​​[i][j]​​​ 表示 ​​word1​​​ 的前 ​​i​​​ 个字母和 ​​word2​​​的前 ​​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 - 1], dp[i][j - 1]), dp[i - 1][j]) + 1

}

我们只需要考虑相差一个如下递推关系:

LeetCode072之编辑距离(相关话题:动态规划)_算法_02

代码实现:

class Solution {
public int minDistance(String word1, String word2) {
int n1 = word1.length();
int n2 = word2.length();
int[][] dp = new int[n1 + 1][n2 + 1];
// 第一行
for (int j = 1; j <= n2; j++) dp[0][j] = dp[0][j - 1] + 1;
// 第一列
for (int i = 1; i <= n1; i++) dp[i][0] = dp[i - 1][0] + 1;

for (int i = 1; i <= n1; i++) {
for (int j = 1; j <= n2; 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 - 1], dp[i][j - 1]), dp[i - 1][j]) + 1;
}
}
return dp[n1][n2];
}
}

 

举报

相关推荐

0 条评论