【python】Leetcode每日一题-不同的子序列

【题目描述】

给定一个字符串 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
^^^

提示:

0 <= s.length, t.length <= 1000
s 和 t 由英文字母组成

【分析】

  • 【超时】思路

    自己原先思路是对 st 顺序匹配,使用dfs遍历,最后时间超时,分析时间复杂度,代码模型为\(O(m^n)\),当然比这个小很多,并不是完整的树结构。

    代码:

    class Solution(object):
    s = ""
    t = ""
    num = 0
    def numDistinct(self, s, t):
    """
    :type s: str
    :type t: str
    :rtype: int
    """
    self.s = s
    self.t = t
    self.dfs(0, 0)
    return self.num def dfs(self, s_index, t_index):
    if(t_index == len(self.t)):
    self.num += 1
    return
    for x in range(len(self.s)-s_index):
    if(self.s[x+s_index] == self.t[t_index]):
    self.dfs(x+s_index+1, t_index+1)
  • 【dp】思路:

    • dp[i][j]表示s[0...i]t[0...j]之间的子序列数。

    • 提供dp转移方程:

    \[\begin{cases}
    dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j];&s[i] == t[j]\\
    dp[i][j] = dp[i - 1][j];&s[i] != t[j]
    \end{cases}
    \]
    • 解释:当s[i] == t[j]时,dp[i][j]可分为s串尾部是否形成匹配两种情况,如果在与t匹配中形成匹配了,则为子序列为dp[i-1][j-1],即除开st两串最后一个字母的子序列数,如果未形成匹配,则为dp[i-1][j],即st两串不包含s串最后一个字母的子序列数。
    • 时间复杂度:\(O(mn)\)

    AC代码:

    class Solution(object):
    def numDistinct(self, s, t):
    """
    :type s: str
    :type t: str
    :rtype: int
    """
    m = len(s)
    n = len(t)
    dp = [[0]*(n+1) for i in range(m+1)]
    for i in range(m+1):
    dp[i][0] = 1
    for i in range(1, m+1):
    for j in range(1, n+1):
    if(j > i):
    continue
    if(s[i-1] == t[j-1]):
    dp[i][j] = dp[i-1][j-1] + dp[i-1][j]
    else:
    dp[i][j] = dp[i-1][j]
    return dp[m][n]
  • 讨论:

    • 看到一位兄弟的评论,图一乐

      去的超时!不过63个测试用例而已,大不了我写63个case

      public class Solution {
      public int NumDistinct(string s, string t) {
      switch(t){
      case "bddabdcae":return 10582116;
      case "bcddceeeebecbc":return 700531452;
      case "ccdeddeabb":return 527764581;
      case "baaacbceabba":return 1293119;
      case "aeacbde":return 2543265;
      case "rwmimatmhydhbujebqehjprrwfkoebcxxqfktayaaeheys":return 543744000;
      case "rwmimatmhydhbujebqehjprarwfkoebcxxqfktayaaeheys":return 1456742400;
      default:return fun(s,t,0,0);
      }
      }
      private int fun(string s,string t,int i,int j){
      int res=0;
      for(;i<s.Length&&j<t.Length;i++){
      if(s[i]==t[j]){
      res+=fun(s,t,i+1,j);
      j++;
      }
      }
      if(j<t.Length)return 0;
      return res+1;
      }
      }
    • 看了官方题解,意识到动态规划边界条件的确也很重要:

      • j=n 时,t[j:] 为空字符串,由于空字符串是任何字符串的子序列,因此对任意 \(0 \le i \le m\),有 \(\textit{dp}[i][n]=1\);

      • i=mj<n 时,s[i:] 为空字符串,t[j:] 为非空字符串,由于非空字符串不是空字符串的子序列,因此对任意 \(0 \le j<n\),有 \(\textit{dp}[m][j]=0\)。

    • 官方题解: 戳这里

【python】Leetcode每日一题-不同的子序列的更多相关文章

  1. 【python】Leetcode每日一题-最长公共子序列

    [python]Leetcode每日一题-最长公共子序列 [题目描述] 给定两个字符串 text1 和 text2,返回这两个字符串的最长 公共子序列 的长度.如果不存在 公共子序列 ,返回 0 . ...

  2. 【python】Leetcode每日一题-132模式

    [python]Leetcode每日一题-132模式 [题目描述] 给定一个整数序列:a1, a2, ..., an,一个132模式的子序列 ai, aj, ak 被定义为:当 i < j &l ...

  3. 【python】Leetcode每日一题-寻找旋转排序数组中的最小元素

    [python]Leetcode每日一题-寻找旋转排序数组中的最小元素 [题目描述] 已知一个长度为 n 的数组,预先按照升序排列,经由 1 到 n 次 旋转 后,得到输入数组.例如,原数组nums ...

  4. 【python】Leetcode每日一题-删除有序数组中的重复项

    [python]Leetcode每日一题-删除有序数组中的重复项 [题目描述] 给你一个有序数组 nums ,请你 原地 删除重复出现的元素,使每个元素 最多出现一次 ,返回删除后数组的新长度. 不要 ...

  5. 【python】Leetcode每日一题-存在重复元素3

    [python]Leetcode每日一题-存在重复元素3 [题目描述] 给你一个整数数组 nums 和两个整数 k 和 t .请你判断是否存在 两个不同下标 i 和 j,使得 abs(nums[i] ...

  6. 【python】Leetcode每日一题-扰乱字符串

    [python]Leetcode每日一题-扰乱字符串 [题目描述] 使用下面描述的算法可以扰乱字符串 s 得到字符串 t : 如果字符串的长度为 1 ,算法停止 如果字符串的长度 > 1 ,执行 ...

  7. 【python】Leetcode每日一题-前缀树(Trie)

    [python]Leetcode每日一题-前缀树(Trie) [题目描述] Trie(发音类似 "try")或者说 前缀树 是一种树形数据结构,用于高效地存储和检索字符串数据集中的 ...

  8. 【python】Leetcode每日一题-打家劫舍2

    [python]Leetcode每日一题-打家劫舍2 [题目描述] 你是一个专业的小偷,计划偷窃沿街的房屋,每间房内都藏有一定的现金.这个地方所有的房屋都 围成一圈 ,这意味着第一个房屋和最后一个房屋 ...

  9. 【python】Leetcode每日一题-二叉搜索树节点最小距离

    [python]Leetcode每日一题-二叉搜索树节点最小距离 [题目描述] 给你一个二叉搜索树的根节点 root ,返回 树中任意两不同节点值之间的最小差值 . 示例1: 输入:root = [4 ...

随机推荐

  1. java二叉树遍历——深度优先(DFS)与广度优先(BFS) 递归版与非递归版

    介绍 深度优先遍历:从根节点出发,沿着左子树方向进行纵向遍历,直到找到叶子节点为止.然后回溯到前一个节点,进行右子树节点的遍历,直到遍历完所有可达节点为止. 广度优先遍历:从根节点出发,在横向遍历二叉 ...

  2. 你真的懂 i++ 和 ++i 吗?

    对于 ++i 和 i++,许多人可能都知道,不就是先加1再取值,和先取值再加1嘛.然而,真的是这样吗?请先看以下4道题,能全部答对可以忽略这篇文章. 题目 // 示例1 int i = 1; i = ...

  3. Caused by: java.lang.RuntimeException: JxBrowser license check failed: No valid license found

    使用jxbrower报错,原因时证书检验失败, 解决方案: 1.首先创建证书,下面是我在IDEA maven项目中创建的位置,Java项目中在src/目录下创建, META-INF/teamdev.l ...

  4. django常用模板语言

    一.变量 django模板接收到从后端传来的参数,放入模板中对应的变量中#django代码 def info(request): .... return render(request,'info.ht ...

  5. mybatis-plus的Could not set property 'updateDate' of 'class com.example.pojo.User' with value 'Fri Jul 24 10:29:39 CST 2020' Cause: java.lang.IllegalArgumentException: argument type mismatch解决方案

    按照官网在写mybatis-plus的自动填充功能一直报错,发现官网的解说不全,数据库是datetime类型,java程序又是date,类型不匹配 org.mybatis.spring.MyBatis ...

  6. Kubernetes 常见问题总结

    Kubernetes 常见问题总结 如何删除不一致状态下的 rc,deployment,service 在某些情况下,经常发现 kubectl 进程挂起现象,然后在 get 时候发现删了一半,而另外的 ...

  7. BUAA_OO_2020_第四单元与课程总结

    BUAA_OO_2020_第四单元与课程总结 第四单元架构 第一次 架构设计 第一次作业要求实现UML类图解析器. 我才用自顶向下依次解析的方法,首先将类图中涉及的所有元素分成三层: 第一层 第二层 ...

  8. leetcode 刷题(数组篇)4题 寻找两个正序数组的中位数(二分查找)

    题目描述 给定两个大小分别为 m 和 n 的正序(从小到大)数组 nums1 和 nums2.请你找出并返回这两个正序数组的 中位数 . 示例 1: 输入:nums1 = [1,3], nums2 = ...

  9. Java性能优化的十条小技巧

    1 System.nanoTime 测试性能时,System.nanoTime比System.currentTimeMills更精确,前者使用纳秒计时,且对系统影响更小. 具体来说: System.c ...

  10. 如何建立一个足够安全的SSH连接?

    1 概述 使用SSH连接服务器是一件很平常的事,但是,连接是否足够安全是一个令人担忧的问题.本文从如下几个方面介绍了如何建立一个足够安全的SSH连接: 端口 协议 用户 密码 密钥对 ssh-agen ...