leetcode刷题笔记-72.编辑距离问题
问题
https://leetcode.cn/problems/edit-distance/
给你两个单词 word1 和 word2, 请返回将 word1 转换成 word2 所使用的最少操作数  。
你可以对一个单词进行如下三种操作:
示例
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 
 | 示例 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')
 
 | 
提示:
| 12
 
 | 0 <= word1.length, word2.length <= 500word1 和 word2 由小写英文字母组成
 
 | 
思路
这道题基于583.两个字符串的删除操作上,将只可以删除一个字符改成了可以进行删除、替换、插入操作。但本质还是两个字符串进行比较,所以大部份代码都是一模一样的,只有比较时两个字符不相同的时候的操作才有区别。
首先是定义dp数组,还是采用常用的定义方式
- dp[i][j]:将字符串1的i之前和字符串2的j之前变成相同字符串的最少操作次数。
然后是确定dp数组的递推,首先是word1[i-1]和word2[j-1]相同和不相同这两种大情况
- 当word1[i-1] == word2[j-1],相当于不需要进行操作,dp[i][j]=dp[i-1][j-1];
- 当word[i-1] != word2[j-1],就需要进行编辑修改了;
当二者不同的时候,有多种方式进行修改,题目给出的是删除、替换、插入。但其实插入和删除是等价的!给出下面这两个字符串
假设我们进行删除,可以从word2中删除b字符,操作数是1;而进行插入是给word1插入一个字符b,操作数也是1。二者的操作数相同,那么递推公式也就相同,所以插入和删除可以认为是一种操作方式!
和583题不同的点就在于有一个替换的操作方式,当两个字符不同的时候,我们可以直接替换其中一个字符串中的字符,替换后两个字符就相等了,也就变成了word1[i-1] == word2[j-1]的情况,dp[i][j]==dp[i-1][j-1]+1;
最终的递推方案如下
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 
 | if (word1[i-1] == word2[j-1]) {
 dp[i][j] = dp[i - 1][j - 1];
 } else {
 
 
 int action1 = dp[i - 1][j] + 1;
 
 int action2 = dp[i][j - 1] + 1;
 
 int action3 = dp[i - 1][j - 1] + 2;
 
 
 int action4 = dp[i - 1][j - 1] + 1;
 
 dp[i][j] =
 min(min(action1, action2), min(action3, action4));
 }
 
 | 
但实际上,这里完全可以省略583题目中两个字符串中都删除字符的操作,因为它的值很明显比替换字符需要的操作数多一次,进行min计算是没有意义的。
初始化和遍历方式都和583题目完全一样,可以去看站内之前写的583题目的题解,这里就不赘述了。
代码
完整代码如下
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 
 | class Solution {public:
 int minDistance(string word1, string word2) {
 size_t sz1 = word1.size(), sz2 = word2.size();
 if (sz1 == 0 || sz2 == 0) {
 return sz1 == 0 ? sz2 : sz1;
 }
 
 vector<vector<int>> dp(sz1 + 1, vector<int>(sz2 + 1, 0));
 
 
 for (int i = 1; i <= sz1; i++) {
 dp[i][0] = i;
 }
 for (int j = 1; j <= sz2; j++) {
 dp[0][j] = j;
 }
 
 for (int i = 1; i <= sz1; i++) {
 for (int j = 1; j <= sz2; j++) {
 if (word1[i - 1] == word2[j - 1]) {
 
 dp[i][j] = dp[i - 1][j - 1];
 } else {
 
 
 int action1 = dp[i - 1][j] + 1;
 
 int action2 = dp[i][j - 1] + 1;
 
 
 
 int action4 = dp[i - 1][j - 1] + 1;
 
 dp[i][j] = min(min(action1, action2), action4);
 
 }
 }
 }
 return dp[sz1][sz2];
 }
 };
 
 | 
