72. 编辑距离 - 力扣(LeetCode)
一、题目
给你两个单词?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) {
if (word1 == null || word2 == null) {
return 0;
}
char[] s1 = word1.toCharArray();
char[] s2 = word2.toCharArray();
// dp[i][j]:s1前缀取前i个字符,编辑成s2前缀取j个字符,将s1的前i个字符组成的前缀串如何用最少编辑代价转换成s2的前j个字符的前缀串,最少代价是多少。
// dp[i][j] = -1表示当前状态下无法编辑成功
int[][] dp = new int[s1.length + 1][s2.length + 1];
// 初始化dp数组 规定dp[0][0] = 0
// 0列s2编辑成s1空串,只能删除
for (int i = 1; i <= s1.length; i++) {
dp[i][0] = 1 * i;
}
// 0行s1空串编辑为s2,只能添加
for (int j = 1; j <= s2.length; j++) {
dp[0][j] = 1 * j;
}
for (int i = 1; i <= s1.length; i++) {
for (int j = 1; j <= s2.length; j++) {
// 分情况讨论
// 可能性1:s1的前i-1个字符可以变成s2的前j个字符,即删掉s1的最后一个i位置的字符即可完成编辑,如果dp[i - 1][j] == -1,说明无法编辑成功,赋值为-1
int p1 = dp[i - 1][j] != -1 ? dp[i - 1][j] + 1 : -1;
// 可能性2:s1的前i个字符先变成str2的前j-1个字符,后再加上s2的最后一个j位置的字符即可完成编辑。如果dp[i][j - 1] == -1,说明无法编辑成功,赋值为-1
int p2 = dp[i][j - 1] != -1 ? dp[i][j - 1] + 1 : -1;
// 可能性3: s1, s2两个字符串最后一个字符串相等,如果str1前面i-1个字符可以编辑成s2前面j-1个字符,那么最后一个字符保留即可完成编辑。
// 可能性4:s1, s2两个字符串最后一个字符串不相等,如果str1前面i-1个字符可以编辑成s2前面j-1个字符,那么最后一个字符替换即可完成编辑。
int p3 = s1[i - 1] == s2[j - 1] ? (dp[i - 1][j - 1] != -1 ? dp[i - 1][j - 1] : -1) : (dp[i - 1][j - 1] != -1 ? dp[i - 1][j - 1] + 1 : -1);
// 取四种情况的最小值
dp[i][j] = Math.min(p1, Math.min(p2, p3));
}
}
// 返回答案
return dp[s1.length][s2.length];
}
}
三、解题思路?
道题最大的难点是将所有的可能性都想出来,不能有遗漏。一共有四种可能:
- 可能性1:s1的前i-1个字符可以变成s2的前j个字符,即删掉s1的最后一个i位置的字符即可完成编辑,如果dp[i - 1][j] == -1,说明无法编辑成功,赋值为-1
- 可能性2:s1的前i个字符先变成str2的前j-1个字符,后再加上s2的最后一个j位置的字符即可完成编辑。如果dp[i][j - 1] == -1,说明无法编辑成功,赋值为-1
- 可能性3: s1, s2两个字符串最后一个字符串相等,如果str1前面i-1个字符可以编辑成s2前面j-1个字符,那么最后一个字符保留即可完成编辑。
- 可能性4:s1, s2两个字符串最后一个字符串不相等,如果str1前面i-1个字符可以编辑成s2前面j-1个字符,那么最后一个字符替换即可完成编辑。
|