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