编辑距离
给你两个单词
word1
和
word2
,
请返回将 word1
转换成 word2
所使用的最少操作数 。
你可以对一个单词进行如下三种操作:
- 插入一个字符
- 删除一个字符
- 替换一个字符
思路
三种操作方式,添加删除替换,也就是说,对于word1来说,我们可以进行三次操作。
和字符串的删除,最长公共子序列类似,此题只不过在不相等时的操作变成了三种,需要分情况讨论。
动规五部曲
确定dp
数组
dp[i][j]
代表了以i-1
结尾的word1转换为以j-1
结尾的word2所使用的最少操作数。
递推公式
-
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-1][j-1]
等之前的已经满足当时的条件了,所以我们只需要考虑当前的两个元素即可。为了让
[0,i-1]
可以转换为[0,j-1]
,我们有以下的操作。-
删除一个元素,删除
i-1
,dp[i][j] = dp[i-1][j] +1
-
添加一个元素,其实就是删除word2的一个元素,
dp[i][j] = dp[i][j-1] + 1
-
替换一个元素,替换
i-1
,dp[i-1][j-1] + 1
三种情况取最小值即可。
-
初始化
根据递推公式,我们发现,需要三个方向的值,所以我们需要初始化dp[i][0] , dp[0][j]
dp[i][0]
代表以i-1为结尾的word1转换为空的最小操作次数,即为i
dp[0][j]
代表空转换为word2需要的最小操作次数为j
遍历顺序
从左到右,从上到下
code
class Solution {
public int minDistance(String word1, String word2) {
int[][] dp = new int[word1.length()+1][word2.length()+1];
// 初始化
for(int i=0;i<word1.length()+1;i++){
dp[i][0] = i;
}
for(int j=1;j<word2.length()+1;j++){
dp[0][j] = j;
}
// 遍历
for(int i=1;i<word1.length()+1;i++){
for(int j=1;j<word2.length()+1;j++){
if(word1.charAt(i-1) == word2.charAt(j-1)){
dp[i][j] = dp[i-1][j-1];
}else{
dp[i][j] = Math.min(dp[i-1][j],Math.min(dp[i][j-1], dp[i-1][j-1])) + 1;
}
}
}
return dp[word1.length()][word2.length()];
}
}