72. 编辑距离
题目来源
题目分析
给定两个单词
word1
和word2
,计算将word1
转换成word2
所使用的最少操作数。可以对单词进行以下三种操作:
- 插入一个字符
- 删除一个字符
- 替换一个字符
题目难度
- 难度:困难
题目标签
- 标签:动态规划
题目限制
1 <= word1.length, word2.length <= 500
word1
和word2
由小写英文字母组成。
解题思路
这道题可以使用动态规划的思想来解决。关键在于定义好状态转移方程。
-
问题定义:设
dp[i][j]
表示将word1[0..i-1]
转换成word2[0..j-1]
所需的最少操作数。最终我们要求的是dp[word1.length][word2.length]
。 -
状态转移:
- 如果
word1[i-1] == word2[j-1]
,则不需要额外操作,dp[i][j] = dp[i-1][j-1]
。 - 如果
word1[i-1] != word2[j-1]
,则需要考虑三种操作:- 插入字符:
dp[i][j] = dp[i][j-1] + 1
- 删除字符:
dp[i][j] = dp[i-1][j] + 1
- 替换字符:
dp[i][j] = dp[i-1][j-1] + 1
- 插入字符:
- 因此,
dp[i][j] = min(dp[i-1][j], dp[i][j-1], dp[i-1][j-1]) + 1
。
- 如果
-
初始化:
dp[i][0]
表示将word1[0..i-1]
转换成空字符串的操作数,显然等于i
。dp[0][j]
表示将空字符串转换成word2[0..j-1]
的操作数,显然等于j
。
-
最终结果:
dp[word1.length][word2.length]
即为所求的最少操作数。
核心算法步骤
-
初始化:
- 创建一个大小为
(word1.length + 1) x (word2.length + 1)
的二维数组dp
,并将dp[i][0]
和dp[0][j]
初始化为i
和j
。
- 创建一个大小为
-
状态转移:
- 遍历
word1
和word2
的所有字符,根据字符是否相等更新dp
数组。
- 遍历
-
输出结果:
- 返回
dp[word1.length][word2.length]
,即word1
转换为word2
所需的最少操作数。
- 返回
代码实现
以下是求解编辑距离问题的 Java 代码:
/**
* 72. 编辑距离
* @param word1 字符串1
* @param word2 字符串2
* @return 最少操作数
*/
public int minDistance(String word1, String word2) {
int n = word1.length();
int m = word2.length();
char[] chars1 = word1.toCharArray();
char[] chars2 = word2.toCharArray();
int[][] dp = new int[n + 1][m + 1];
for (int i = 0; i <= n; i++) {
dp[i][0] = i;
}
for (int i = 0; i <= m; i++) {
dp[0][i] = i;
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (chars1[i] == chars2[j]) {
dp[i + 1][j + 1] = dp[i][j];
} else {
dp[i + 1][j + 1] = Math.min(Math.min(dp[i][j + 1], dp[i + 1][j]), dp[i][j]) + 1;
}
}
}
return dp[n][m];
}
代码解读
minDistance
方法:dp[i][j]
表示word1[0..i-1]
和word2[0..j-1]
的最小编辑距离。- 如果
word1[i-1]
和word2[j-1]
相等,则不需要操作,dp[i+1][j+1] = dp[i][j]
。 - 否则,选择插入、删除或替换操作中最小的一个,
dp[i+1][j+1] = min(dp[i][j+1], dp[i+1][j], dp[i][j]) + 1
。
性能分析
- 时间复杂度:
O(n * m)
,其中n
和m
分别为word1
和word2
的长度。 - 空间复杂度:
O(n * m)
,因为我们使用了二维数组来存储中间结果。
测试用例
你可以使用以下测试用例来验证代码的正确性:
String word1 = "horse";
String word2 = "ros";
int result1 = minDistance(word1, word2);
System.out.println(result1);
// 输出: 3 (将 "horse" 转换为 "ros" 需要 3 步操作)
word1 = "intention";
word2 = "execution";
int result2 = minDistance(word1, word2);
System.out.println(result2);
// 输出: 5 (将 "intention" 转换为 "execution" 需要 5 步操作)
扩展讨论
优化写法
- 空间优化:
- 可以将
dp
数组压缩为一维,使用滚动数组来优化空间复杂度。
- 可以将
其他实现
- 递归 + 记忆化:
- 也可以通过递归加记忆化的方法来解决该问题,从
word1
和word2
的尾部开始,逐步求解最小编辑距离。
- 也可以通过递归加记忆化的方法来解决该问题,从
总结
通过动态规划的思想,我们能够高效地解决编辑距离问题。通过合理定义 dp
数组的含义,状态转移方程,以及对初始状态的处理,可以解决类似的字符串转换问题。