【LeetCode】115. Distinct Subsequences 解题报告(Python)

这个题是要求不同子序列有几种组法,给定一个字符串 S 和一个字符串 T,计算在 S 的子序列中 T 出现的个数。

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

输入:S = “rabbbit”, T = “rabbit”
输出:3
解释:

如下图所示, 有 3 种可以从 S 中得到 “rabbit” 的方案。
(上箭头符号 ^ 表示选取的字母)

rabbbit
^^^^ ^^
rabbbit
^^ ^^^^
rabbbit
^^^ ^^^
解题思路:

  1. 这是一道非常经典的动态规划问题,一般遇到两个字符串的问题,很大可能都是动态规划,照常先画表格
    在这里插入图片描述

  2. 考虑初始化dp数组
    (1)如果s1,s2都为空,那么结果是一种,也就是说dp[0][0] = 1
    (2)如果s2为空,那么结果s1中一定包含空字符串,也就是说dp[0][len(s2)] = 1
    (3)如果s1为空,s2不为空,那么s1中一定不包含s2,也就是说第一列除了dp[0][0]位置都为0
    在这里插入图片描述

  3. 填充第一行
    当s1[0] = s2[0] = r时,r的组法一种,dp[1][1] = 1,后面与r都不同,所以都是1
    在这里插入图片描述

  4. 找此方法写完
    在这里插入图片描述

  5. 一边找矩阵规律,一边思考题意
    找矩阵规律分为两种情况:
    (1)s1==s2,相等时怎么变的,(另,相等时一般与dp[i-1][j-1]相关)
    (2)s1 != s2,不等时怎么变的,(另,不相等时一般与dp[i][j-1],dp[i-1][j]相关,有时也会与dp[i-1][j-1]相关)
    思考题意,相等时,可以不可考虑当前位,那么dp[i][j]就是由dp[i-1][j-1]转化而来的,考虑当前位,在有s2[j]时已经有n一种组成,而当前又相等,那么组成情况应该在多一个n种组成,那么规律就出来了
    dp[i][j] = dp[i-1][j-1] + dp[i][j-1]
    思考题意,不相等时,可以不考虑当前位,不要这一位已经又n种情况,因为当前位不等要了这一位应该还是n种,那么规律就出来了
    dp[i][j] = dp[i][j-1]

  6. 对比矩阵,发现规律没有问题,完成

提交代码:(动态规划,Runtime: 128 ms, faster than 84.21 % )

class Solution:
    def numDistinct(self, s: str, t: str) -> int:
        dp = [([0] * (len(s)+1)) for _ in range(len(t)+1)]
        for _ in range(len(s) + 1):
            dp[0][_] = 1
        for i in range(len(t)):
            for j in range(len(s)):
                if t[i] == s[j]:
                    dp[i + 1][j + 1] = dp[i + 1][j] + dp[i][j]
                else:
                    dp[i + 1][j + 1] = dp[i + 1][j]
        return dp[-1][-1]
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值