583. 两个字符串的删除操作 - 力扣(Leetcode)
思路:
-
使用动态规划
-
-
确定dp数组以及下标的含义
dp[i][j]
的定义为:以word1[i]为结尾和以word2[j]为结尾的字符串最大相同连续子序列的长度
-
确定递推公式
// 状态转移方程 // 相等的时候就只要将长度加一 if(word1[i -1 ] == word2[j - 1]) { dp[i][j] = dp[i - 1][j - 1] + 1; } else { // 不相等的时候要考虑删去word1[i - 1]的情况和删去word2[j - 1]的情况 dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]); }
-
dp数组如何初始化
vector< vector<int> > dp(word1.size() + 1, vector<int>(word2.size() + 1, 0));
-
确定遍历顺序
从 i = 1 和 j = 1 开始从前往后遍历
-
我的AC代码
// 时间复杂度O(n x m),空间复杂度O(n x m)
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(); ++i) {
for(int j = 1; j <= word2.size(); ++j) {
if(word1[i -1 ] == word2[j - 1]) {
dp[i][j] = dp[i - 1][j - 1] + 1;
}
else {
dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
}
}
}
return (word1.size() + word2.size() - 2 * dp[word1.size()][word2.size()]);
}
};
标准答案
直接考虑删除次数
// 时间复杂度O(n x m),空间复杂度O(n x m)
class Solution {
public:
int minDistance(string word1, string word2) {
vector<vector<int>> dp(word1.size() + 1, vector<int>(word2.size() + 1));
for (int i = 0; i <= word1.size(); i++) dp[i][0] = i;
for (int j = 0; j <= word2.size(); j++) dp[0][j] = j;
for (int i = 1; i <= word1.size(); i++) {
for (int j = 1; j <= word2.size(); j++) {
if (word1[i - 1] == word2[j - 1]) {
dp[i][j] = dp[i - 1][j - 1];
} else {
dp[i][j] = min(dp[i - 1][j] + 1, dp[i][j - 1] + 1);
}
}
}
return dp[word1.size()][word2.size()];
}
};
考虑最长公共子序列
// 时间复杂度O(n x m),空间复杂度O(n x m)
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(); i++){
for (int j=1; j<=word2.size(); j++){
if (word1[i-1] == word2[j-1]) dp[i][j] = dp[i-1][j-1] + 1;
else dp[i][j] = max(dp[i-1][j], dp[i][j-1]);
}
}
return word1.size()+word2.size()-dp[word1.size()][word2.size()]*2;
}
};
72. 编辑距离 - 力扣(LeetCode)
思路:
-
使用动态规划
-
-
确定dp数组以及下标的含义
- dp[i][j]的定义为:以i -1为结尾和以j - 1为结尾的字符串需要编辑距离的次数
-
确定递推公式
// 状态转移方程 // 分两种情况 // 第一种情况,两个字符相等,那么不需要编辑 // 即dp[i][j] = dp[i - 1][j - 1]; // 第二种情况 // 两个字符不相等,那么就有三种操作,取其中的最小值 // 让word1删字符,dp[i - 1][j] + 1 // 让word2删字符,dp[i][j - 1] + 1 // 替换字符,dp[i - 1][j - 1] + 1 if(word1[i - 1] == word2[j - 1]) { dp[i][j] = dp[i - 1][j - 1]; } else { dp[i][j] = min(min(dp[i][j - 1] + 1, dp[i - 1][j] + 1), dp[i - 1][j - 1] + 1); }
-
dp数组如何初始化
for(int i = 1; i <= word1.size(); ++i) { dp[i][0] = i; } for(int i = 1; i <= word2.size(); ++i) { dp[0][i] = i; }
-
确定遍历顺序
// 从前往后
-
我的AC代码
// 时间复杂度O(n*m),空间复杂度O(n*m)
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(); ++i) {
dp[i][0] = i;
}
for(int i = 1; i <= word2.size(); ++i) {
dp[0][i] = i;
}
for(int i = 1; i <= word1.size(); ++i) {
for(int j = 1; j <= word2.size(); ++j) {
if(word1[i - 1] == word2[j - 1]) {
dp[i][j] = dp[i - 1][j - 1];
}
else {
dp[i][j] = min(min(dp[i][j - 1] + 1, dp[i - 1][j] + 1), dp[i - 1][j - 1] + 1);
}
}
}
return dp[word1.size()][word2.size()];
}
};
标准答案
// 时间复杂度O(n*m),空间复杂度O(n*m)
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(); i++) dp[i][0] = i;
for (int j = 0; j <= word2.size(); j++) dp[0][j] = j;
for (int i = 1; i <= word1.size(); i++) {
for (int j = 1; j <= word2.size(); j++) {
if (word1[i - 1] == word2[j - 1]) {
dp[i][j] = dp[i - 1][j - 1];
}
else {
dp[i][j] = min({dp[i - 1][j - 1], dp[i - 1][j], dp[i][j - 1]}) + 1;
}
}
}
return dp[word1.size()][word2.size()];
}
};
Comments NOTHING