题目
给定两个单词 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')
详解和代码如下:
import org.springframework.util.StringUtils;
/***
*
* 给定两个单词 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')
*
* 动态规划实现:其实就是把两个字符串从头到尾两个for循环计算word1[0-i]和word2[0-j]相匹配时的最小操作数
* 因为有最优子特性,所以可以从下往上来递推
*/
public class 编辑距离 {
public static int minDistance(String word1, String word2) {
if (StringUtils.isEmpty(word1)) {
return word2.toCharArray().length;
}
if (StringUtils.isEmpty(word2)) {
return word1.toCharArray().length;
}
int m = word1.length();
int n = word2.length();
//定义dp数组,dp[i][j] 表示word1的第i为和word2的j位相同时需要操作几次,
// 注意此时dp[0-i][0-j]之间的位,两个字符串已经相同了,这是关键
//所以最后的int[m][n]就是结果了,就是两个word完全相同了
int[][] dp = new int[m + 1][n + 1];
//初始化边界条件
for (int i = 1; i <= m; i++) {
dp[i][0] = dp[i - 1][0] + 1;
}
for (int j = 1; j <= n; j++) {
dp[0][j] = dp[0][j-1] + 1;
}
//定义dp方程:前面dp数组已经定义了,dp方程就比较简单了,
// 当word1[i]==word[j]时:dp[i][j] = dp[i-1][j-1] 此时不需要任何操作
// 当word1[i]!=word[j]时:就需要操作了,怎么操作呢?有三种:
// 如果删除,删除代表word[i]位需要删除掉 比如:word1:abce word2 abc空 此时 i=3,j=2时需要删除e
// 删除的情况 dp[i][j] = dp[i-1][j]+1, 表示当前word1[i]与word2[j]是不匹配的,那我去找下word1[i-1]与word2[j]匹配的情况,如果该情况下最小,那就删除当前的word1[i]
// 更新的情况:dp[i][j] = dp[i-1][j-1]+1 表示第i个字符需要替换
// 插入的情况:dp[i][j] = dp[i][j-1]+1 表示当前word1[i]与word2[j]是不匹配的,那我就去看看dp[i][j-1]匹配的时候的值然后新增一个数word[i+1] = word[j]就行了
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], Math.min(dp[i - 1][j - 1], dp[i][j - 1])) + 1;
}
}
}
return dp[m][n];
}
public static void main(String[] args) {
System.out.println(minDistance("plasma","altruism"));
}
}