583. 两个字符串的删除操作
题目链接:. - 力扣(LeetCode)
讲解视频:
题目描述:
给定两个单词 word1
和 word2
,返回使得 word1
和 word2
相同所需的最小步数。每步 可以删除任意一个字符串中的一个字符。
示例 1:
输入: word1 = "sea", word2 = "eat" 输出: 2 解释: 第一步将 "sea" 变为 "ea" ,第二步将 "eat "变为 "ea"
示例 2:
输入:word1 = "leetcode", word2 = "etco" 输出:4
解题思路:
本题可以转换成先找到两个字符串中最长重复子序列,用两个字符串长度分别减去公共子序列长度再求和。
最长重复子序列解题思路链接:最长重复子序列
代码:
class Solution {
public:
int minDistance(string word1, string word2) {
int n = word1.size(), m = word2.size();
vector<vector<int>> dp(m+1,vector<int>(n+1));
int ret = 0;
for(int i = 1; i <= m; i++)
{
for(int j = 1; j <= n; j++)
{
if(word1[j-1] == word2[i-1]) dp[i][j] = dp[i-1][j-1] + 1;
else dp[i][j] = max(dp[i-1][j],dp[i][j-1]);
ret = max(ret,dp[i][j]);
}
}
return m + n - ret * 2;
}
};
72. 编辑距离
题目链接:. - 力扣(LeetCode)
讲解视频:
题目描述:
给你两个单词 word1
和 word2
, 请返回将 word1
转换成 word2
所使用的最少操作数 。
你可以对一个单词进行如下三种操作:
- 插入一个字符
- 删除一个字符
- 替换一个字符
示例 1:
输入:word1 = "horse", word2 = "ros" 输出:3 解释: horse -> rorse (将 'h' 替换为 'r') rorse -> rose (删除 'r') rose -> ros (删除 'e')
解题思路:
1、状态表示:
dp[i][j] 表示:以下标i为结尾的字符串word1和以下标j为结尾的字符串word2的最小编辑距离
2、状态转移方程:
1)当word1[i] == word2[j]时,不用任何编辑,
dp[i][j]
就应该是dp[i - 1][j - 1]
,即dp[i][j] = dp[i - 1][j - 1];
2)当word1[i] != word2[j]时,有如下三种操作:
- 操作一:word1删除一个元素,那么就是以下标i - 2为结尾的word1 与 j-1为结尾的word2的最近编辑距离 再加上一个操作。即
dp[i][j] = dp[i - 1][j] + 1;
- 操作二:word2删除一个元素,那么就是以下标i - 1为结尾的word1 与 j-2为结尾的word2的最近编辑距离 再加上一个操作。即
dp[i][j] = dp[i][j - 1] + 1;
- 操作三:替换元素,
word1
替换word1[i - 1]
,使其与word2[j - 1]
相同,此时不用增删加元素。可以回顾一下,if (word1[i - 1] == word2[j - 1])
的时候我们的操作 是dp[i][j] = dp[i - 1][j - 1]
对吧。那么只需要一次替换的操作,就可以让 word1[i - 1] 和 word2[j - 1] 相同。所以dp[i][j] = dp[i - 1][j - 1] + 1;
对于添加元素逻辑是:word2添加一个元素,相当于word1删除一个元素,例如
word1 = "ad" ,word2 = "a"
,word1
删除元素'd'
和word2
添加一个元素'd'
,变成word1="a", word2="ad"
, 最终的操作数是一样!
3、初始化:当word1为空串时,只要将word2内元素全部删除即可得到word1,因此操作次数为word2字符串长度;同理,当word2为空串时,word1内元素全部删除即可得到word2,因此操作次数为word1字符串长度
4、遍历顺序:
填表顺序先「从上往下」再「从左往右」。
5、返回值:
返回dp[m][n]。
代码:
class Solution {
public:
int minDistance(string word1, string word2) {
int m = word1.size();
int n = word2.size();
word1 = " " + word1;
word2 = " " + word2;
vector<vector<int>> dp(m+1,vectorQ<int>(n+1));
for(int i = 0; i <= n; i++) dp[0][i] = i;
for(int i = 0; i <= m; i++) dp[i][0] = i;
for(int i = 1; i <= m; i++)
{
for(int j = 1; j <= n; j++)
{
if(word1[i] == word2[j])
dp[i][j] = dp[i-1][j-1];
else
dp[i][j] = min({dp[i-1][j],dp[i][j-1],dp[i-1][j-1]}) + 1;
}
}
return dp[m][n];
}
};