0072. 编辑距离 #
- 标签:字符串、动态规划
- 难度:困难
题目大意 #
描述:给定两个单词 $word1$、$word2$。
对一个单词可以进行以下三种操作:
- 插入一个字符
- 删除一个字符
- 替换一个字符
要求:计算出将 $word1$ 转换为 $word2$ 所使用的最少操作数。
说明:
- $0 \le word1.length, word2.length \le 500$。
- $word1$ 和 $word2$ 由小写英文字母组成。
示例:
- 示例 1:
|
|
- 示例 2:
|
|
解题思路 #
思路 1:动态规划 #
1. 划分阶段 #
按照两个字符串的结尾位置进行阶段划分。
2. 定义状态 #
定义状态 $dp[i][j]$ 表示为:「以 $word1$ 中前 $i$ 个字符组成的子字符串 $str1$」变为「以 $word2$ 中前 $j$ 个字符组成的子字符串 $str2$」,所需要的最少操作次数。
3. 状态转移方程 #
- 如果当前字符相同($word1[i - 1] = word2[j - 1]$),无需插入、删除、替换。$dp[i][j] = dp[i - 1][j - 1]$。
- 如果当前字符不同($word1[i - 1] \ne word2[j - 1]$),$dp[i][j]$ 取源于以下三种情况中的最小情况:
- 替换($word1[i - 1]$ 替换为 $word2[j - 1]$):最少操作次数依赖于「以 $word1$ 中前 $i - 1$ 个字符组成的子字符串 $str1$」变为「以 $word2$ 中前 $j - 1$ 个字符组成的子字符串 $str2$」,再加上替换的操作数 $1$,即:$dp[i][j] = dp[i - 1][j - 1] + 1$。
- 插入($word1$ 在第 $i - 1$ 位置上插入元素):最少操作次数依赖于「以 $word1$ 中前 $i - 1$ 个字符组成的子字符串 $str1$」 变为「以 $word2$ 中前 $j$ 个字符组成的子字符串 $str2$」,再加上插入需要的操作数 $1$,即:$dp[i][j] = dp[i - 1][j] + 1$。
- 删除($word1$ 删除第 $i - 1$ 位置元素):最少操作次数依赖于「以 $word1$ 中前 $i$ 个字符组成的子字符串 $str1$」变为「以 $word2$ 中前 $j - 1$ 个字符组成的子字符串 $str2$」,再加上删除需要的操作数 $1$,即:$dp[i][j] = dp[i][j - 1] + 1$。
综合上述情况,状态转移方程为:
$dp[i][j] = \begin{cases} dp[i - 1][j - 1] & word1[i - 1] = word2[j - 1] \cr min(dp[i - 1][j - 1], dp[i - 1][j], dp[i][j - 1]) + 1 & word1[i - 1] \ne word2[j - 1] \end{cases}$
4. 初始条件 #
- 当 $i = 0$,「以 $word1$ 中前 $i$ 个字符组成的子字符串 $str1$」为空字符串,「$str1$」变为「以 $word2$ 中前 $j$ 个字符组成的子字符串 $str2$」时,至少需要插入 $j$ 次,即:$dp[0][j] = j$。
- 当 $j = 0$,「以 $word2$ 中前 $j$ 个字符组成的子字符串 $str2$」为空字符串,「以 $word1$ 中前 $i$ 个字符组成的子字符串 $str1$」变为「$str2$」时,至少需要删除 $i$ 次,即:$dp[i][0] = i$。
5. 最终结果 #
根据状态定义,最后输出 $dp[sise1][size2]$(即 $word1$ 变为 $word2$ 所使用的最少操作数)即可。其中 $size1$、$size2$ 分别为 $word1$、$word2$ 的字符串长度。
思路 1:代码 #
|
|
思路 1:复杂度分析 #
- 时间复杂度:$O(n \times m)$,其中 $n$、$m$ 分别是字符串 $word1$、$word2$ 的长度。两重循环遍历的时间复杂度是 $O(n \times m)$,所以总的时间复杂度为 $O(n \times m)$。
- 空间复杂度:$O(n \times m)$。用到了二维数组保存状态,所以总体空间复杂度为 $O(n \times m)$。