☆打卡算法☆LeetCode 115、 不同的子序列 算法解析

举报
恬静的小魔龙 发表于 2022/04/20 08:46:33 2022/04/20
【摘要】 推荐阅读CSDN主页GitHub开源地址Unity3D插件分享简书地址我的个人博客QQ群:1040082875大家好,我是小魔龙,Unity3D软件工程师,VR、AR,虚拟仿真方向,不定时更新软件开发技巧,生活感悟,觉得有用记得一键三连哦。 一、题目 1、算法题目“给定一个字符串s和字符串t,计算s的子序列中t出现的个数。”题目链接:来源:力扣(LeetCode)链接: 115. 不同的子...

推荐阅读

大家好,我是小魔龙,Unity3D软件工程师,VR、AR,虚拟仿真方向,不定时更新软件开发技巧,生活感悟,觉得有用记得一键三连哦。

一、题目

1、算法题目

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

题目链接:

来源:力扣(LeetCode)

链接: 115. 不同的子序列

2、题目描述

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

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

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

示例 1:
输入:s = "rabbbit", t = "rabbit"
输出:3
解释:
如下所示,3 种可以从 s 中得到 "rabbit" 的方案。
rabbbit
rabbbit
rabbbit
示例 2:
输入:s = "babgbag", t = "bag"
输出:5
解释:
如下所示,5 种可以从 s 中得到 "bag" 的方案。 
babgbag
babgbag
babgbag
babgbag
babgbag

二、解题

1、思路分析

这道题可以考虑使用动态规划的方法阶梯,假设字符串s和t的长度为m和n,要算s的子序列在t中出现的个数,那么s的长度一定大于或等于t的长度,也就是只有当m≥n的时候,个数才大于0,如果m≤n,就直接返回0。

创建二维数组dp,其中dp[i][j]表示前 t[i] 个字符可以由 s[j] 字符串组成的个数。

所以动态规划方程:
当 s[j] == t[i] , dp[i][j] = dp[i-1][j-1] + dp[i][j-1]

当s[j] != t[i] , dp[i][j] = dp[i][j-1]

通过动态方程,最终计算得到dp[0][0]即为在s的子序列中t出现的个数。

2、代码实现

代码参考:

class Solution {
    public int numDistinct(String s, String t) {
        int m = s.length(), n = t.length();
        if (m < n) {
            return 0;
        }
        int[][] dp = new int[m + 1][n + 1];
        for (int i = 0; i <= m; i++) {
            dp[i][n] = 1;
        }
        for (int i = m - 1; i >= 0; i--) {
            char sChar = s.charAt(i);
            for (int j = n - 1; j >= 0; j--) {
                char tChar = t.charAt(j);
                if (sChar == tChar) {
                    dp[i][j] = dp[i + 1][j + 1] + dp[i + 1][j];
                } else {
                    dp[i][j] = dp[i + 1][j];
                }
            }
        }
        return dp[0][0];
    }
}

image.png

3、时间复杂度

时间复杂度 : O(mn)

其中m和n分别是字符串s和t的长度,对于二维数组来说,需要对dp中每个元素进行计算。

空间复杂度: O(mn)

其中m和n分别是字符串s和t的长度。

三、总结

题解中的关键:

s[i] == t[j]的时候, s[i] 可以选择自己是否跟 t[j]匹配

  • 如果匹配,那么 dp[i][j] 其中一部分数量就是 dp[i+1][j+1]
  • 如果选择不匹配(这样可以让前面的字符跟t[j]匹配,毕竟t 短的,s 长) dp[i][j] 另外一部分就是 dp[i+1][j]

所以才会有:

dp[i][j] = dp[i+1][j+1] + dp[i+1][j]
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。