代码随想录Day45|115.不同的子序列、583. 两个字符串的删除操作、72. 编辑距离

115.不同的子序列

题目链接:Leetcode
文章讲解:代码随想录
视频讲解:bilibili

解题思路

  这题一开始想用滚动数组的办法做,后来发现并不行,因为要去的是连续,并且可以跳元素,但是总体顺序不能变,因此需要从前往后遍历,这就不满足滚动数组需要的倒序遍历了。和连续情况不一样的是,即使当前的元素不相等,也要找到前面符合要求的最长子序列,保证后续结果正确。

解法
class Solution {
public:
    int numDistinct(string s, string t) {
        int n1 = s.size();
        int n2 = t.size();
        if(n2 > n1) return 0;
        vector<vector<uint64_t>> dp(n2+1, vector<uint64_t>(n1+1, 0));
        for(int j=0; j < n1; j++)    dp[0][j] = 1;
        for(int i=1; i<=n2; i++){
            for(int j=1; j<=n1; j++){
                if(t[i-1]==s[j-1])
                    dp[i][j] = dp[i-1][j-1] + dp[i][j-1];   // 加上前面满足条件的个数
                else
                    dp[i][j] = dp[i][j-1];
            }
        }
        return dp[n2][n1];
    }
};
  • 时间复杂度: O ( m n ) O(mn) O(mn)
  • 空间复杂度: O ( m n ) O(mn) O(mn)

583. 两个字符串的删除操作

题目链接:Leetcode
文章讲解:代码随想录
视频讲解:bilibili

解题思路

  和上一题很类似,变成了两个字符串都可删除。在递推的时候就是针对两个字符串对应下标的元素为尾元素进行,当尾元素相同时,dp[i][j]=dp[i-1][j-1],不相同时,dp[i][j]=min(dp[i-1][j]+1, dp[i][j-1] +1, dp[i-1][j-1]+2,以此保证对于每一个为尾元素得到的步数都是最小的呢,那么最终结果即为dp[n1][n2[

解法
class Solution {
public:
    int minDistance(string word1, string word2) {
        int n1 = word1.size();
        int n2 = word2.size();
        vector<vector<int>> dp(n1+1, vector<int>(n2+1, 0));
        for(int i=0; i<=n1; i++)    dp[i][0] = i;
        for(int j=1; j<=n2; j++)    dp[0][j] = j;
        for(int i=1; i<=n1; i++){
            for(int j=1; j<=n2; 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, min(dp[i][j-1]+1, dp[i-1][j-1]+2));
                }
            }
        }
        return dp[n1][n2];
    }
};
  • 时间复杂度: O ( m n ) O(mn) O(mn)
  • 空间复杂度: O ( m n ) O(mn) O(mn)

72. 编辑距离

题目链接:Leetcode
文章讲解:代码随想录
视频讲解:bilibili

解题思路

  需要一点转化。这里一个字符串的添加操作可以等效为另一个字符串的删除操作,因此需要考虑的数量就减少了,替换操作相当于在两个字符串上一个下标匹配成功的基础上添加上相同的元素,因此最小的dp就在这三者之间,当尾元素相同时不需要操作。

解法
class Solution {
public:
    int minDistance(string word1, string word2) {
        int n1 = word1.size();
        int n2 = word2.size();
        vector<vector<int>> dp(n1+1, vector<int>(n2+1, 0));
        for(int i=0; i<=n1; i++)    dp[i][0] = i;
        for(int j=1; j<=n2; j++)    dp[0][j] = j;
        for(int i=1; i<=n1; i++){
            for(int j=1; j<=n2; 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, min(dp[i][j-1]+1, dp[i-1][j-1]+1));
                }
            }
        }
        return dp[n1][n2];
    }
};

  • 时间复杂度: O ( m n ) O(mn) O(mn)
  • 空间复杂度: O ( m n ) O(mn) O(mn)

今日总结

  国庆在忙答辩,补卡中()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值