0
点赞
收藏
分享

微信扫一扫

力扣算法学习day38-3

fbd4ffd0717b 2022-03-10 阅读 69

文章目录

力扣算法学习day38-3

115-不同的子序列

题目

image-20220301000312038

image-20220301000402075

代码实现

class Solution {
    // public int numDistinct(String s, String t) {
    //     // 直接想到的方法,超时了。 我用idea测试在本地测试了一下超时的那个案例,
    //     // 和下面正确解法的答案是一样的,这种方法应该可以,只是这道题会运行超时。
    //     char[] tList = t.toCharArray();
    //     char[] sList = s.toCharArray();
    //     // 如下,可以看出规律,类似深度遍历的思想。
    //     //    r a b b b i t            b a b g b a g
    //     // r  1 0 0 0 0 0 0         b  1 0 1 0 1 0 0
    //     // a  0 1 0 0 0 0 0         a  0 1 0 0 0 1 0
    //     // b  0 0 1 1 1 0 0         g  0 0 0 1 0 0 1            2 + 1 + 1 + 1
    //     // b  0 0 1 1 1 0 0             
    //     // i  0 0 0 0 0 1 0
    //     // t  0 0 0 0 0 0 1     2+1+1
    //     boolean[][] dp = new boolean[tList.length][sList.length];

    //     for(int i = 0;i < tList.length;i++){
    //         for(int j = 0;j < sList.length;j++){
    //             if(tList[i] == sList[j]){
    //                 dp[i][j] = true;
    //             }
    //         }
    //     }

    //     return sum(0,0,dp);
    // }
    // public int sum(int count,int index,boolean[][] dp){
    //     if(count == dp.length - 1){
    //         int sum = 0;
    //         for(int i = index;i < dp[count].length;i++){
    //             if(dp[count][i]){
    //                 sum++;
    //             }
    //         }
    //         return sum;
    //     }

    //     int sum = 0;
    //     for(int i = index;i < dp[count].length;i++){
    //         if(dp[count][i]){
    //             sum += sum(count+1,i+1,dp);
    //         }
    //     }

    //     return sum;
    // }


    public int numDistinct(String s, String t) {
        char[] tList = t.toCharArray();
        char[] sList = s.toCharArray();
        // dp
        // dp[i][j]:表示以i-1结尾的s子序列中以j-1结尾的t的子序列出现的次数。
        // 如果sList[i-1] == tList[j-1],那么有两种匹配情况
        // 1.sList[i-1]元素用于匹配时的种数:
        // 迭代公式:dp[i-1][j-1]      即i-2的s的子字符串和j-2结尾的t的子字符串的结果的个数即为匹配时的个数。
        // 2.sList[i-1]不用于匹配,比如s 为 bagg,t 为bag,可以是第一个g匹配,也可以是第二个。种数:
        // 迭代公式:dp[i-1][j]
        // 所以如果sList[i-1] == tList[j-1],dp[i][j] = dp[i-1][j-1] + dp[i-1][j];
        // 如果sList[i-1] != tList[j-1],那么此时的元素不匹配,那么不用它,取上一个s的情况
        // 故,迭代公式:dp[i][j] = dp[i-1][j];
        int[][] dp = new int[sList.length+1][tList.length+1];

        // 初始化
        // 1.dp[0][i]需要初始化为0,因为s为空时,肯定合不出t。
        // 2.dp[i][0]需要初始化为1.因为t为空时,s相当于全部减去后,都能匹配。其中应该包括dp[0][0]这个特殊位置。
        // 注:通知也是为了迭代方程可以成立。
        for(int i = 0;i < dp.length;i++){
            dp[i][0] = 1;
        }

        // 遍历顺序的话都行,看懂迭代公式基本就懂了。 注:已测试,确实都可以。速度9ms
        // for(int j = 1;j < dp[0].length;j++){
        //     for(int i = 1;i < dp.length;i++){
        //         if(sList[i-1] == tList[j-1]){
        //             dp[i][j] = dp[i-1][j-1] + dp[i-1][j];
        //         } else{
        //             dp[i][j] = dp[i-1][j];
        //         }
        //     }
        // }

        // 不过这种遍历方式会更快。 速度 5ms
        for(int i = 1;i < dp.length;i++){
            for(int j = 1;j < dp[i].length;j++){
                if(sList[i-1] == tList[j-1]){
                    dp[i][j] = dp[i-1][j-1] + dp[i-1][j];
                } else{
                    dp[i][j] = dp[i-1][j];
                }
            }
        }

        return dp[sList.length][tList.length];
    }

}
举报

相关推荐

0 条评论