大家好!我是曾续缘🙃
今天是《LeetCode 热题 100》系列
发车第 95 天
多维动态规划第 5 题
❤️点赞 👍 收藏 ⭐再看,养成习惯
给你两个单词
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')提示:
难度:💖💖
0 <= word1.length, word2.length <= 500
word1
和word2
由小写英文字母组成
解题方法
编辑距离,又称Levenshtein距离,是指将一个字符串转换为另一个字符串所需要的最少编辑操作次数。
初始化二维数组
java
int[][] f = new int[n + 1][m + 1];
我们创建一个二维数组f
,其大小为(n+1) x (m+1)
。这里n
和m
分别是word1
和word2
的长度。这样的设计是为了处理边界情况,即一个空字符串转换到另一个非空字符串的情况。
填表过程
初始化第一行和第一列
javafor (int i = 1; i <= n; i++) { f[i][0] = i; } for (int i = 0; i <= m; i++) { f[0][i] = i; }
这一步是为了设置边界情况,即从一个空字符串转换到任意长度字符串所需的操作数,以及从任意长度字符串转换到空字符串所需的操作数。
- 当
word2
为空时,无论word1
的长度是多少,转换成空字符串只需要进行删除操作,因此f[i][0] = i
。 - 当
word1
为空时,无论word2
的长度是多少,从空字符串转换成word2
只需要进行插入操作,因此f[0][j] = j
。
- 当
填充剩余的单元格
javafor (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) { if (word1.charAt(i - 1) == word2.charAt(j - 1)) { f[i][j] = f[i - 1][j - 1]; } else { f[i][j] = Math.min(Math.min(f[i - 1][j], f[i][j - 1]), f[i - 1][j - 1]) + 1; } } }
在这个循环中,我们检查
word1
和word2
相应位置的字符是否相同。- 如果
word1
的第i
个字符等于word2
的第j
个字符,那么不需要进行操作,直接继承之前的操作数,即f[i][j] = f[i - 1][j - 1]
。 - 如果不同,我们需要考虑三种操作:
- 删除一个字符。删除的字符不能匹配了,看
f[i - 1][j]
- 插入一个字符。插入的字符和
word2
第j
个字符匹配了,看f[i][j - 1]
- 替换一个字符。替换的字符和
word2
第j
个字符匹配了,看f[i - 1][j - 1]
- 我们取这三种操作中的最小值,然后加一,得到
f[i][j]
的值。
- 删除一个字符。删除的字符不能匹配了,看
- 如果
最终结果
java
return f[n][m];
最后,我们返回f[n][m]
的值,这表示将word1
转换为word2
所需的最少操作数。
Code
查看代码
java
class Solution {
public int minDistance(String word1, String word2) {
int n = word1.length();
int m = word2.length();
int[][] f = new int[n + 1][m + 1];
for (int i = 1; i <= n; i++) {
f[i][0] = i;
}
for (int i = 0; i <= m; i++) {
f[0][i] = i;
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
if (word1.charAt(i - 1) == word2.charAt(j - 1)) {
f[i][j] = f[i - 1][j - 1];
} else {
f[i][j] = Math.min(Math.min(f[i - 1][j], f[i][j - 1]), f[i - 1][j - 1]) + 1;
}
}
}
return f[n][m];
}
}