题目描述:
给你两个单词 word1
和 word2
, 请返回将 word1
转换成 word2
所使用的最少操作数 。
你可以对一个单词进行如下三种操作:
- 插入一个字符
- 删除一个字符
- 替换一个字符
解题思路:
第一步:确定dp变量:dp[i][j]:代表word1从第i个字母,转换到word2的第j个字母所需要的最少操作数;
第二步:初始化dp:
初始化第一行:i=0时,word1为空,此时从word1转换成word2的过程就可以被看作是插入一个字符的操作,操作步数就等于word2的长度;
初始化第一列:j=0时,word2为空,此时从word1转换成word2的过程就可以被看作是删除一个字符的操作,操作步数就等于word1的长度;
第三步:确定状态转移方程:dp
对于dp[i][j],
dp[i][j-1] 为 word1的前 i 个字符和 word 2的前 j - 1 个字符编辑距离的子问题。即对于 word 2的第 j 个字符,我们在word 1的末尾添加了一个相同的字符,那么 dp[i][j] 最小可以为 dp[i][j-1] + 1;
dp[i-1][j] 为 word1的前 i - 1 个字符和 word 2的前 j 个字符编辑距离的子问题。即对于word1 的第 i 个字符,我们在word 2 的末尾添加了一个相同的字符,那么 D[i][j] 最小可以为 D[i-1][j] + 1;
dp[i-1][j-1] 为 word1 前 i - 1 个字符和 B 的前 j - 1 个字符编辑距离的子问题。即对于 word 2 的第 j 个字符,我们修改 word1的第 i 个字符使它们相同,那么 dp[i][j] 最小可以为 dp[i-1][j-1] + 1。尤其是,如果 word1的第 i 个字符和 word 2 的第 j 个字符原本就相同,那么我们实际上不需要进行修改操作,此时,dp[i][j] 最小可以为 dp[i-1][j-1]
由此可以得出:当word1.charAt(i-1)==word2.charAt(j-1)时 , dp[i][j]=dp[i-1][j-1];
当word1.charAt(i-1)!=word2.charAt(j-1)时,dp[i][j]=Math.min(dp[i-1][j-1],Math.min(dp[i-1][j], dp[i][j-1]) )+1;
public int minDistance(String word1, String word2) {
int m=word1.length(),n=word2.length();
//设置dp变量:dp[i][j]:代表word1从第i个字母,转换到word2的第j个字母所学要的最少操作数
int[][] dp=new int[m+1][n+1];
//初始化
dp[0][0]=0;
for (int i = 1; i <=n; i++) {
dp[0][i]=dp[0][i-1]+1;
}
for (int i = 1; i <= m; i++) {
dp[i][0]=dp[i-1][0]+1;
}
//确定状态转移方程:
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; 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-1],Math.min(dp[i-1][j], dp[i][j-1]) )+1;
}
}
}
return dp[m][n];
}