题目描述
给你两个单词 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’)
提示:
0 <= word1.length, word2.length <= 500
word1
和word2
由小写英文字母组成
代码
class Solution {
public int minDistance(String word1, String word2) {
int N = 510, n = word1.length(), m = word2.length();
int[][] f = new int[N][N];
// word1长度是0的时候,插入字符
// word2长度是0的时候,删除字符
for (int i = 0; i < N; i++) {
f[0][i] = i;
f[i][0] = i;
}
char[] w1 = word1.toCharArray(), w2 = word2.toCharArray();
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
int fi = i + 1, fj = j + 1;
// 在word1的后面插入一个字符,从word1中删除一个字符
f[fi][fj] = Math.min(f[fi][fj - 1] + 1, f[fi - 1][fj] + 1);
// 字符相等,
if (w1[i] == w2[j]) f[fi][fj] = Math.min(f[fi][fj], f[fi - 1][fj - 1]);
// 字符不相等,就替换
else f[fi][fj] = Math.min(f[fi][fj], f[fi - 1][fj - 1] + 1);
}
}
return f[n][m];
}
}
思路
闫式DP分析法,状态表示是f[i][j]
,代表word1字符串的前i个字符变成word2前j个字符的最小操作数。至于状态怎么来的,这种就是我做过类似的题目,一看就想出来的。
接下来就是状态转移了,具体情况具体分析,可以拿案例来分析。
从word1转换成word2支持三种操作,分别为:
- 插入一个字符
- 删除一个字符
- 替换一个字符
不相等的情况
拿案例1做讨论,把三种操作都用上,word1 = “horse”, word2 = “ros”,假设i=4,j=2。
e != s,有以下的情况
- 把e替换成s,
f[i][j] = min(f[i][j], f[i - 1][j - 1] + 1)
不相等肯定是直接替换,那么就需要在word1="hors"替换成"ro"的最小步骤数的基础上加1。 - 把e删除掉,
f[i][j] = min(f[i][j], f[i - 1][j] + 1)
如果把e删除掉,f[i - 1][j] 就是把word1="hors"换成"ros"需要的最小步骤数,删除本身是一个操作,所以需要加上1。 - 在e后面插入一个s,
f[i][j] = max(f[i][j], f[i][j - 1] + 1)
这里的f[i][j - 1]
就是表示把word1="horse"换成"ro"的最小步骤数,然后word1再插入一个"s"字符,就是word1=“ros”,也是一种方案。
相等的情况
拿案例1做讨论,把三种操作都用上,word1 = “horss”, word2 = “ros”,假设i=3,j=2。
- s=s,不做任何操作,
f[i][j] = min(f[i][j], f[i - 1][j - 1])
- 删除word1的s,
f[i][j] = min(f[i][j], f[i - 1][j] + 1)
- 在s后边插入一个s,
f[i][j] = min(f[i][j], f[i][j - 1] + 1)
总结起来
两种情况都需要删除和插入操作,所以
f[i][j] = min(f[i - 1][j] + 1, f[i][j - 1] + 1)
如果word1[i] == word2[j] 有 f[i][j] = min(f[i][j], f[i - 1][j - 1])
如果word1[i] != word2[j] 有 f[i][j] = min(f[i][j], f[i - 1][j - 1] + 1)