题目链接:583. 两个字符串的删除操作
dp
数组 : 以i - 1
为结尾的word1
和以j - 1
为结尾的word2
相同的最少操作为dp[i][j]
步
递推公式:
dp[i][j] = (word1[i - 1] == word2[j - 1])
? dp[i - 1][j - 1]
: max(dp[i - 1][j] + 1, dp[i][j - 1] + 1);
dp[i - 1][j - 1]
dp[i - 1][j - 1]
相当于word1
删除了第i - 1
个元素,word2
删除了第j - 1
个元素。因为word1[i - 1]
和word2[j - 1]
是一样的,所以删除后步骤不变max(dp[i - 1][j] + 1, dp[i][j - 1] + 1);
dp[i - 1][j] dp[i][j - 1]
中最大的初始化:
二维数组初始化第一行和第一列。
dp[i][0] = i
dp[0][j] = j
class Solution {
public:
int minDistance(string word1, string word2) {
vector<vector<int>> dp(word1.size() + 1, vector<int>(word2.size() + 1, 0));
for (int i = 0; i < word1.size() + 1; ++i) dp[i][0] = i;
for (int j = 0; j < word2.size() + 1; ++j) dp[0][j] = j;
for (int i = 1; i < word1.size() + 1; ++i) {
for (int j = 1; j < word2.size() + 1; ++j) {
dp[i][j] = (word1[i - 1] == word2[j - 1])
? dp[i - 1][j - 1]
: min(dp[i - 1][j] + 1, dp[i][j - 1] + 1);
}
}
return dp.back().back();
}
};
可以用1143.最长公共子序列 的思路来算,word1
和word2
的公共求出,结果一相减也就求出。
class Solution {
public:
int minDistance(string word1, string word2) {
vector<vector<int>> dp(word1.size() + 1, vector<int>(word2.size() + 1, 0));
for (int i = 1; i < word1.size() + 1; ++i) {
for (int j = 1; j < word2.size() + 1; ++j) {
dp[i][j] = (word1[i - 1] == word2[j - 1])
? dp[i - 1][j - 1] + 1
: max(dp[i - 1][j], dp[i][j - 1]);
}
}
return word1.size() + word2.size() - 2 * dp.back().back();
}
};
题目链接:72. 编辑距离
如果word1
转化到word2
需要删除字母,相当于word2
转换到word1
添加字母 。
换而言之,长的单词转化为短的单词,只需要 删除 和 替换 操作即可。
dp
数组 : 以i - 1
为结尾的word1
和以j - 1
为结尾的word2
相同的最少操作为dp[i][j]
步
递推公式:
dp[i][j] = (word1[i - 1] == word2[j - 1])
? dp[i - 1][j - 1]
: min({dp[i - 1][j], dp[i][j - 1], dp[i - 1][j - 1]}) + 1;
dp[i - 1][j - 1]
dp[i - 1][j - 1]
因为是一样的,所以操作步骤不变min({dp[i - 1][j], dp[i][j - 1], dp[i - 1][j - 1]}) + 1;
单词长度不同选择删除
dp[i - 1][j]
相当于 word1
删除了第i - 1
个字母
dp[i][j - 1]
相当于 word2
删除了第j - 1
个字母
单词长度相同选择替换
dp[i - 1][j - 1]
相当于word1
中的第i - 1
个字母和word2
中的第j - 1
个字母不同,进行替换
初始化:
二维数组初始化第一行和第一列。
由于单词长度不同,因此选择删除操作进行初始化:dp[i][0] = i
dp[0][j] = j
class Solution {
public:
int minDistance(string word1, string word2) {
vector<vector<int>> dp(word1.size() + 1, vector<int>(word2.size() + 1, 0));
for (int i = 0; i < word1.size() + 1; ++i) dp[i][0] = i;
for (int j = 0; j < word2.size() + 1; ++j) dp[0][j] = j;
for (int i = 1; i < word1.size() + 1; ++i) {
for (int j = 1; j < word2.size() + 1; ++j) {
dp[i][j] = (word1[i - 1] == word2[j - 1])
? dp[i - 1][j - 1]
: min({dp[i - 1][j], dp[i][j - 1], dp[i - 1][j - 1]}) + 1;
}
}
return dp.back().back();
}
};
首先,数组dp[i][j]
要设置为从 i - 1
j - 1
的表述方式,是为了初始化简单;其次,根据题意来比较,来对递推公式的细节分支的计算;最后就是为了服务于dp
数组进行初始化,遍历顺序。
基本上所有的二维dp
数组都可以压缩到一维,但是可能会造成代码的可读性太差。