题目
给出两个单词 word1 和 word2,找出将 word1 转换成 word2 所使用的最少的步骤数 (每个操作记为一步)。
你可以对一个单词进行以下三种操作:
a) 插入一个字符
b) 删除一个字符
c) 替换一个字符
思路
动态规划的题目
- 递归
dp[i][j]:表示word1[1..i]编辑成为word2[1..j]所需要的操作数
d("abbc","acc") = d("abb","ac")
= 1 + min(d("ab","a"), // 替换
d("abb","a"), //添加
d("ab",“ac”)) //删除
上述一个递归过程:
- 如果字符串最后一个相等,两个字符串-1
- 如果不相等:
2.1 替换操作:需要求得d(两个字符串-1)的最小距离
2.2 添加操作:添加之前的状态就是,d(当前字符串编辑成为模式串-1)
2.3 删除操作:删除之前的状态就是,d(当前字符串删掉一个后编辑成为模式串)
2里的每个操作+1
-
动态规划
递推:d(i, j) 表示把 str1 前 i 个字符编辑成 str2 前 j 个字符所需要的最小 edit distanced(2, 1) = 1 + d(1, 1)
edit("ab", "a") = 1 + edit("a", "a") <- delete "b" from str1
d(1, 2) = 1 + d(1, 1)
edit("a", "ab") = 1 + edit("a", "a") <- insert "b" into str1
d(2, 2) = 1 + d(1, 1)
edit("ab", "ac") = 1 + edit("a", "a") <- replace "b" with "c" in str1
代码
public int minDistance(String word1, String word2) {
int m = word1.length();
int n = word2.length();
int[][] dp = new int[m + 1][n + 1];
//init
//str2 == ""
for (int i = 0; i <= m; i++) {
dp[i][0] = i;
}
//str1 == ""
for (int j = 0; j <= n; j++) {
dp[0][j] = 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 - 1], Math.min(dp[i-1][j],dp[i][j-1])) + 1;
}
}
}
return dp[m][n];
}