代码随想录算法训练营 day 55: ● 392.判断子序列 ● 115.不同的子序列

76 阅读2分钟

392. Is Subsequence

这题用双指针做是O(m+n), 用动规是O(m * n)。只是练习。

dp[i][j]为s的[0,i-1]子串,为t的[0, j-1]的子串的子序列长度。 递推公式为, dp[i][j]在s[i-1] == t[j-1]时,为dp[i-1][j-1] + 1,否则为dp[i-1][j]与dp[i][j-1]的较大者。 剪枝操作是若dp[i][j]等于s的长度,就可以返回了。但先遍历s的话就没什么用。

class Solution {
    public boolean isSubsequence(String s, String t) {
        int[][] dp = new int[s.length() + 1][t.length() + 1];

        for(int i=1; i<s.length() + 1; i++) {
            char chars = s.charAt(i-1);
            for(int j=1; j<t.length() + 1; j++) {
                char chart = t.charAt(j-1);

                if(chars == chart) {
                    dp[i][j] = dp[i-1][j-1] + 1;
                }
                else {
                    dp[i][j] = Math.max(dp[i-1][j], dp[i][j-1]);
                }

                if(dp[i][j] == s.length()) {
                    return true;
                }
            }
        }

        return dp[s.length()][t.length()] == s.length();
    }
}

115. Distinct Subsequences

这题定义dp数组为s的前i-1个元素,包含t的j-1个元素子序列的个数为dp[i][j]。 递推公式为: 当s[i-1] == t[j-1]时, dp[i][j]为dp[i-1][j-1] + dp[i-1][j],即为s不用最后一个s[i-1]做匹配,但使用倒数第二个元素做匹配的情形,加上s使用最后一个元素s[i-1]做匹配的情形。

当s[i-1] != t[j-1]时,dp[i][j]为dp[i-1][j],因为最后一个元素肯定不能进入当前匹配了,相当于删除的情形

初始化要注意,需要把dp[0-end][0]都初始化为1,意义就是s的[0,i]子串,含有一个空串t[0,0]的个数为1.

class Solution {
    public int numDistinct(String s, String t) {
        int[][] dp = new int[s.length() + 1][t.length() + 1];
        
        for(int i=0; i<s.length()+1; i++) {
            dp[i][0] = 1;
        }

        for(int i=1; i<=s.length(); i++) {
            char chars = s.charAt(i-1);
            for(int j=1; j<=t.length(); j++) {
                char chart = t.charAt(j-1);

                if(chars == chart) {
                    dp[i][j] = dp[i-1][j-1] + dp[i-1][j];
                }
                else {
                    dp[i][j] = dp[i-1][j];
                }
            }
        }

        return dp[s.length()][t.length()];
    }
}