代码随想录算法训练营第56天 |583. 两个字符串的删除操作、72. 编辑距离

发布于 2023-08-19  1,544 次阅读


583. 两个字符串的删除操作 - 力扣(Leetcode)

思路:

  • 使用动态规划

    1. 确定dp数组以及下标的含义

      • dp[i][j]的定义为:以word1[i]为结尾和以word2[j]为结尾的字符串最大相同连续子序列的长度
    2. 确定递推公式

      // 状态转移方程
      // 相等的时候就只要将长度加一
      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]);
      }
    3. dp数组如何初始化

      vector< vector<int> > dp(word1.size() + 1, vector<int>(word2.size() + 1, 0));
    4. 确定遍历顺序

      从 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)

思路:

  • 使用动态规划

    1. 确定dp数组以及下标的含义

      • dp[i][j]的定义为:以i -1为结尾和以j - 1为结尾的字符串需要编辑距离的次数
    2. 确定递推公式

      // 状态转移方程
      // 分两种情况
      // 第一种情况,两个字符相等,那么不需要编辑
      // 即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);
      }
    3. 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;
      }
    4. 确定遍历顺序

      // 从前往后

我的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()];
    }
};