代码随想录算法训练营第五十四天| 动态规划

Posted by Zhuoqun on March 8, 2023

392.判断子序列

跟昨天做的两道题也很像,用昨天的代码也可以写出来。我自己又重新手写了一遍,出现了一个小马虎,就是在最后DP的值是否等于 s的长度的时候,我写成了dp[s.length()-1][t.length()-1],但其实应该用dp[s.length()][t.length()],因为在这道题里我们设了一个比s和t都大一个的二维数组。

class Solution {
public:
    bool isSubsequence(string s, string t) {
        vector<vector<int>> dp (s.length()+1,vector<int>(t.length()+1,0));

        for(int i=1; i<=s.length(); i++){
            for(int j=1; j<=t.length(); j++){
                if(s[i-1] == t[j-1]){
                    dp[i][j] = dp[i-1][j-1]+1;
                }
                else{
                    dp[i][j] = max(dp[i-1][j],dp[i][j-1]);
                }
            }
        }
        if(dp[s.length()][t.length()] == s.length()){
            return true;
        }
        else{
            return false;
        }

    }
};

115.不同的子序列

这道题自己没想出来。但是现在基本上理解了。

首先是dp的含义,dp是当前应有多少种答案。详细点解释就是:当s的长度i,t的长度为j时,dp[i][j]表示有多少种结果。

然后是初始化,外循环是长的string,内循环是短的string。因为我们要遍历完一遍长的string才知道到底有多少种结果。所以当s(短的)为0的时候,那么不管t(长的)有多少长,就应该有1种答案。如果t是0,那么就不应该有任何答案,也就是等于0。

然后我们对于dp的取值:当两个数一样的时候,那dp就应该等于左上方的值和上方的值。左上方的值代表之前有多少个数一致,上方旳值是继承之前找到了多少种答案。

具体的逻辑还需要再多想想。

class Solution {
public:
    int numDistinct(string s, string t) {
        vector<vector<uint64_t>> dp(s.size() + 1, vector<uint64_t>(t.size() + 1));
        
        for (int i = 0; i < s.size(); i++) dp[i][0] = 1;
        for (int j = 1; j < t.size(); j++) dp[0][j] = 0;
        
        for(int i=1; i<=s.size(); i++){
            for(int j=1; j<=t.size();j++){
                if(s[i-1] == t[j-1]){
                    dp[i][j] = dp[i-1][j-1] + dp[i-1][j];
                }
                else{
                    dp[i][j] = dp[i-1][j];
                }
            }
        }
        return dp[s.size()][t.size()];

    }
};