583. 两个字符串的删除操作
给定两个单词 word1 和 word2 ,返回使得 word1 和 word2 相同所需的最小步数。 每步 可以删除任意一个字符串中的一个字符。
示例 1: 输入: word1 = "sea", word2 = "eat" 输出: 2 解释: 第一步将 "sea" 变为 "ea" ,第二步将 "eat "变为 "ea" 示例 2: 输入:word1 = "leetcode", word2 = "etco" 输出:4
提示:
- 1 <= word1.length, word2.length <= 500
- word1 和 word2 只包含小写英文字母
思路
1. 确定dp数组(dp table)以及下标的含义
我们可以定义一个二维数组 dp,其中 dp[i][j] 表示 word1 的前 i 个字符和 word2 的前 j 个字符相同所需的最小步数。
2. 确定递推公式
- 当
word1[i-1] == word2[j-1]时,dp[i][j] = dp[i-1][j-1]。 - 否则,
dp[i][j] = min(dp[i-1][j], dp[i][j-1]) + 1。
3. dp数组如何初始化
dp[0][j] = j,表示将word2的前j个字符变为空字符串需要的步数。dp[i][0] = i,表示将word1的前i个字符变为空字符串需要的步数。
4. 确定遍历顺序
从上到下,从左到右遍历。
5. 举例推导dp数组
以 word1 = "sea" 和 word2 = "eat" 为例:
初始化:
"" e a t
"" 0 1 2 3
s 1
e 2
a 3
填充:
"" e a t
"" 0 1 2 3
s 1 2 3 4
e 2 1 2 3
a 3 2 1 2
最终答案是 dp[3][3] = 2。
题解
class Solution {
public:
int minDistance(string word1, string word2) {
int m = word1.size();
int n = word2.size();
vector<vector<int>> dp(m + 1, vector<int>(n + 1, 0));
// 3. dp数组初始化
for (int i = 0; i <= m; ++i) {
dp[i][0] = i;
}
for (int j = 0; j <= n; ++j) {
dp[0][j] = j;
}
// 4. 确定遍历顺序
for (int i = 1; i <= m; ++i) {
for (int j = 1; j <= n; ++j) {
// 2. 递推公式
if (word1[i-1] == word2[j-1]) {
dp[i][j] = dp[i-1][j-1];
} else {
dp[i][j] = min(dp[i-1][j], dp[i][j-1]) + 1;
}
}
}
return dp[m][n];
}
};
72. 编辑距离
给你两个单词 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 由小写英文字母组成
思路
1. 确定dp数组(dp table)以及下标的含义
我们可以定义一个二维数组 dp,其中 dp[i][j] 表示 word1 的前 i 个字符转换成 word2 的前 j 个字符所使用的最少操作数。
2. 确定递推公式
- 当
word1[i-1] == word2[j-1]时,dp[i][j] = dp[i-1][j-1]。 - 否则,
dp[i][j] = min(dp[i-1][j], dp[i][j-1], dp[i-1][j-1]) + 1。
3. dp数组如何初始化
dp[0][j] = j,表示将空字符串转换为word2的前j个字符需要的步数。dp[i][0] = i,表示将word1的前i个字符转换为空字符串需要的步数。
4. 确定遍历顺序
从上到下,从左到右遍历。
5. 举例推导dp数组
以 word1 = "horse" 和 word2 = "ros" 为例:
初始化:
"" r o s
"" 0 1 2 3
h 1
o 2
r 3
s 4
e 5
填充:
"" r o s
"" 0 1 2 3
h 1 1 2 3
o 2 2 1 2
r 3 2 2 2
s 4 3 3 2
e 5 4 4 3
最终答案是 dp[5][3] = 3。
题解
class Solution {
public:
int minDistance(string word1, string word2) {
int m = word1.size();
int n = word2.size();
vector<vector<int>> dp(m + 1, vector<int>(n + 1, 0));
// 3. dp数组初始化
for (int i = 0; i <= m; ++i) {
dp[i][0] = i;
}
for (int j = 0; j <= n; ++j) {
dp[0][j] = j;
}
// 4. 确定遍历顺序
for (int i = 1; i <= m; ++i) {
for (int j = 1; j <= n; ++j) {
// 2. 递推公式
if (word1[i-1] == word2[j-1]) {
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];
}
};