130、★LeetCode-115.不同的子序列

题目:

给定一个字符串 s 和一个字符串 t ,计算在 s 的子序列中 t 出现的个数。

字符串的一个 子序列 是指,通过删除一些(也可以不删除)字符且不干扰剩余字符相对位置所组成的新字符串。(例如,"ACE" 是 "ABCDE" 的一个子序列,而 "AEC" 不是)

题目数据保证答案符合 32 位带符号整数范围。

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/distinct-subsequences

思路:

1. dp数组记录,此时分别以当前位置字符结尾时,子序列的数目!

2.当前字符相同,就可以将各自减一的个数(当前互相匹配) + 之前减一的s中已经包含的t的数目!

3.当前字符不同,只用将之前s减一时包含的此时t的个数挪下来即可!

需要初始化,每一行第一列的个数为1!

代码:

1)动态规划:时间复杂度为 O(N^2)

class Solution {
    public int numDistinct(String s, String t) {
        //还是进行子序列的比较,之前只是判断是否为子序列,此时要计算
        int s1 = s.length();
        int t1 = t.length();

        int[][] dp = new int[s1 + 1][t1 + 1];
        //初始化!将每一行的第一列初始化为1
        for(int i = 0;i < s1;i++){
            dp[i][0] = 1;
        }
        for(int i = 1;i <= s1;i++){
            for(int j = 1;j <= t1;j++){
                if(s.charAt(i - 1) == t.charAt(j - 1)){
                    //相同:将上挪下来 + 上左
                    dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j];
                }
                else{
                    //不相同:直接挪下来即可
                    dp[i][j] = dp[i - 1][j];
                }
            }
        }
        return dp[s1][t1];
    }
}

2)使用滚动数组,优化空间复杂度

class Solution {
    public int numDistinct(String s, String t) {
        //还是进行子序列的比较,之前只是判断是否为子序列,此时要计算
        int s1 = s.length();
        int t1 = t.length();

        //进行优化:一维数组;
        //二维数组中看出来,只用到了上一行的内容;只用倒着进行更新,不会使用到当前行的内容即可
        int[] dp = new int[t1 + 1];
        dp[0] = 1;
        for(int i = 1;i <= s1;i++){//更新的层:从上往下走
            for(int j = t1;j > 0;j--){//更新列时:从后往前,防止覆盖
                if(s.charAt(i - 1) == t.charAt(j - 1)){
                    dp[j] = dp[j] + dp[j - 1];
                }
                //其他情况时,不用进行更新
            }
        }
        return dp[t1];
    }
}

你可能感兴趣的:(动态规划,leetcode,算法,动态规划)