Leetcode 剑指 Offer II 097.不同的子序列

news2024/10/5 14:50:52

题目难度: 困难

原题链接

今天继续更新 Leetcode 的剑指 Offer(专项突击版)系列, 大家在公众号 算法精选 里回复 剑指offer2 就能看到该系列当前连载的所有文章了, 记得关注哦~

题目描述

给定一个字符串 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 由英文字母组成

题目思考

  1. t 要想成为 s 的子序列, 要满足什么条件? 是否可以从单个字符的角度出发?

解决方案

  • 分析题目, 要想求在 s 的子序列中 t 出现的个数, 我们先来考虑各自的最后一个字符s[-1]t[-1], 不难发现有三种情况:
    1. s[-1]等于t[-1]
    2. s[-1]不等于t[-1]
  • 对于情况 1, 有两种选择:
    1. 使用t[-1], 需要继续判断s[-2]是否与t[-2]相等;
    2. 不使用t[-1], 需要继续判断s[-2]是否与t[-1]相等
  • 对于情况 2, 只有一种选择:
    1. 无法使用t[-1], 所以需要继续判断s[-2]是否与t[-1]相等
  • 不难发现当前结果和前面的结果存在转移关系, 可以尝试用动态规划来解决
  • 我们维护 s 的前 i 个字符的所有子序列中, t 的前 j 个字符出现的次数, 那么上面的情况 1 就可以从(i-1,j)(i-1,j-1)下标对转移而来, 而情况 2 则可以从(i-1,j)下标对转移而来, 这就是典型的动态规划的思想
  • 用数学语言来表示: 假设dp[i][j]代表以 s 的前 i 个字符的所有子序列中, t 的前 j 个字符出现的次数, 那么就有:
    • if s[i-1]==t[j-1]:
      • dp[i][j] = dp[i-1][j] + dp[i-1][j-1]
    • else:
      • dp[i][j] = dp[i-1][j]
  • 最终结果就是dp[len(s1)][len(s2)]
  • 注意当 j 为 0 时, 其 dp 值为 1, 因为总是可以包含空串; 而当该条件不满足且 i 为 0 时, 其 dp 值为 0, 因为空串不可能存在非空子序列
  • 下面的代码中使用记忆化搜索实现, 更加直观, 而且有详细的注释, 方便大家理解
复杂度
  • 时间复杂度 O(MN): 假设 s 和 t 的长度分别是 M 和 N, 需要两重循环求 DP 值
  • 空间复杂度 O(MN): 二维记忆化搜索的空间消耗
代码
class Solution:
    def numDistinct(self, s: str, t: str) -> int:
        # 记忆化搜索, dp(i,j)表示s的前i个字符的所有子序列中, t的前j个字符出现的次数, 结果就是dp(len(s),len(t))
        @functools.cache
        def dp(i, j):
            if j == 0:
                # 当j为0时, 返回1, 因为总是可以包含空串
                return 1
            if i == 0:
                # 当上面条件不满足且i为0时, 返回0, 因为空串不可能存在非空子序列
                return 0
            # 两种情况都可以从(i-1,j)转移而来
            res = dp(i - 1, j)
            if s[i - 1] == t[j - 1]:
                # 当末尾两字符相等时, 还可以从(i-1,j)转移而来, 累加其计数
                res += dp(i - 1, j - 1)
            return res

        return dp(len(s), len(t))

大家可以在下面这些地方找到我~😊

我的 GitHub

我的 Leetcode

我的 CSDN

我的知乎专栏

我的头条号

我的牛客网博客

我的公众号: 算法精选, 欢迎大家扫码关注~😊

算法精选 - 微信扫一扫关注我

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2190041.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

NVIDIA网卡系列之ConnectX-5规格信息(100G-PCIe 3.0x16-8PF512VF-2016年发布)

背景 NVIDIA ConnectX-5系列的网卡&#xff0c;早期还在Mellanox未被NVIDIA收购的时候就发布了&#xff0c;主流支持100G&#xff0c;主要用在PCIe3.0&#xff0c;最大支持200G的产品。虽然已经发布多年&#xff0c;但是目前还是在大量使用。100Gbps的速率对比普通网卡来讲&am…

基于SSM的电影院售票系统设计与实现

文未可获取一份本项目的java源码和数据库参考。 前言 近些年的电影在人们文娱活动中占据重要地位&#xff0c;另外&#xff0c;由于人们的生活越来越富有&#xff0c;越来越多的人们不再选择在家里看电影&#xff0c;而是选择去电影院看电影。但是&#xff0c;以往的售票方式是…

在Visual Studio中使用CMakeLists.txt集成EasyX库的详细指南

EasyX库是一款专为Windows平台设计的轻量级C图形库&#xff0c;适合初学者和教育领域使用。结合Visual Studio和CMake工具链&#xff0c;用户可以轻松创建C项目&#xff0c;并集成EasyX库&#xff0c;实现丰富的图形编程效果。本文将详细介绍如何在Visual Studio中通过CMakeLis…

分布式事务(Seata-AT模式)

角色说明 TC (Transaction Coordinator) - 事务协调者 维护全局和分支事务的状态,驱动全局事务提交或回滚。 TM (Transaction Manager) - 事务管理器 定义全局事务的范围:开始全局事务、提交或回滚全局事务。 RM (Resource Manager) - 资源管理器 管理分…

macOS编译和运行prometheus2.54

欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码)&#xff1a;https://github.com/zq2599/blog_demos 本篇概览 本文详述了在macOS(M2芯片)上编译和运行prometheus2.54版本的过程&#xff0c;以及安装node_exporter和grafana并使用prometheus指标进行展示 本地…

【含文档】基于Springboot+Vue的活力健身馆管理系统(含源码+数据库+lw)

1.开发环境 开发系统:Windows10/11 架构模式:MVC/前后端分离 JDK版本: Java JDK1.8 开发工具:IDEA 数据库版本: mysql5.7或8.0 数据库可视化工具: navicat 服务器: SpringBoot自带 apache tomcat 主要技术: Java,Springboot,mybatis,mysql,vue 2.视频演示地址 3.功能 系统定…

HTB:Preignition[WriteUP]

连接至HTB服务器并启动靶机 靶机IP&#xff1a;10.129.157.49 分配IP&#xff1a;10.10.16.12 1.Directory Brute-forcing is a technique used to check a lot of paths on a web server to find hidden pages. Which is another name for this? (i) Local File Inclusion, (…

喜欢听音乐的朋友,怎么能少这个音乐插件?

喜欢听音乐的朋友有福利了&#xff0c;今天小编给大家带来一个非常酷的音乐插件&#xff0c;让你的音乐在桌面跳动起来~&#xff01;想象一下&#xff0c;随着旋律的起伏&#xff0c;你的桌面仿佛被赋予了生命&#xff0c;音符跳跃、光影交错&#xff0c;每一首歌都化作了眼前流…

电源入口防护电路

电源入口防护电路 原则:先防护&#xff0c;后防反&#xff0c;最后滤波基本防护器件防反措施 原则:先防护&#xff0c;后防反&#xff0c;最后滤波 在设计电路保护方案时&#xff0c;遵循“先防护&#xff0c;后防反&#xff0c;最后滤波”的原则是非常重要的。这种顺序确保了…

Python入门--函数

目录 1. 函数介绍 2. 函数的定义 3. 函数的参数 4. 函数的返回值 5. 函数说明文档 6. 函数的嵌套调用 7. 函数的作用域 (1). 局部变量 (2). 全局变量 (3). global关键字 1. 函数介绍 函数&#xff1a;是组织好的&#xff0c;可重复使用的&#xff0c;用来实现特定功能…

【无题】夜入伊人笑愉,泪湿心夜难眠。

在这句诗中&#xff0c;意境描绘了一种深沉的情感体验&#xff0c;充满了温柔与哀愁。诗人通过“夜入伊人笑愉”开启了一段梦境之旅&#xff0c;其中“夜入”象征着进入梦境的状态。在这个梦幻的世界里&#xff0c;诗人与心爱的人欢笑嬉戏&#xff0c;那份快乐和亲昵如同真实的…

java高并发场景RabbitMQ的使用

场景是面试时被问到&#xff0c;一次性请求100多万个前端请求&#xff0c;请问你如果进行后端处理。因为之前的电商也没有一次性这么大的业务量&#xff0c;所以只是前端nginx做了对应的负载均衡技术。所以回答的不是那么流畅。面试官的回答你可以用RabbitMQ做分流,削峰,异步处…

什么是 ARP 欺骗和缓存中毒攻击?

如果您熟悉蒙面歌王&#xff0c;您就会明白蒙面歌王的概念&#xff1a;有人伪装成别人。然后&#xff0c;当面具掉下来时&#xff0c;您会大吃一惊&#xff0c;知道了这位名人是谁。类似的事情也发生在 ARP 欺骗攻击中&#xff0c;只是令人惊讶的是&#xff0c;威胁行为者利用他…

中小型网络系统综合实验

一、实验要求 1.pc端自动获取ip地址&#xff0c;可以互通访问&#xff0c;可以访问域名解析服务器 2.设置vlan&#xff0c;三层交换机实现不同vlan之间的交流 3.设置静态路由&#xff0c;配置nat地址转换&#xff0c;实现全网可达 二、实验思路 1.首先给LSW2配置vlan 10 &a…

双十一不能错过的好物推荐!强推五款超好用的品牌好物

双十一快到了&#xff0c;这个时候的优惠力度都是最大的&#xff0c;还不知道买啥的小伙伴们赶紧来看这篇好物推荐&#xff01;以下五款产品是我花了几天时间精心挑选出来的&#xff0c;看完之后保证你想加入购物车&#xff01; 品牌好物推荐一、希亦CG超声波清洗机 如果你带眼…

用Manim实现高尔顿板(Galton Board)

高尔顿板的介绍 高尔顿板&#xff08;Galton Board&#xff09;&#xff0c;有时也称为贝尔图&#xff08;Bean Machine&#xff09;&#xff0c;是由英国统计学家弗朗西斯高尔顿&#xff08;Francis Galton&#xff09;于19世纪末发明的一种物理装置&#xff0c;用于演示随机分…

【智能算法应用】蒲公英优化算法求解二维路径规划问题

摘要 在二维路径规划问题中&#xff0c;通常需要在不规则的障碍物环境中找到一条从起点到终点的最优路径。本文应用蒲公英优化算法&#xff08;DOA&#xff09;进行路径规划&#xff0c;其能够有效避开障碍物并找到最短路径。通过实验验证&#xff0c;DOA具有收敛速度快、全局…

2024年【金属非金属矿山(露天矿山)安全管理人员】模拟试题及金属非金属矿山(露天矿山)安全管理人员模拟考试题库

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 金属非金属矿山&#xff08;露天矿山&#xff09;安全管理人员模拟试题参考答案及金属非金属矿山&#xff08;露天矿山&#xff09;安全管理人员考试试题解析是安全生产模拟考试一点通题库老师及金属非金属矿山&#…

SAP学习笔记 - Basis01 - 创建Client ,拷贝Client

最近工作当中用到了Client间数据移送的内容&#xff0c;想把自己的虚机给弄两个Client。 最后也没完全弄成&#xff0c;先把过程整理一下&#xff0c;以后有空接着弄。 目录 1&#xff0c;SALE - 新建逻辑系统 2&#xff0c;SCC4 - 分配Client到集团 3&#xff0c;RZ10 - 取…

算法【Java】—— 二叉树的深搜

深搜 深搜简单来说就是一直递归到底&#xff0c;然后返回&#xff0c;以二叉树为例&#xff0c;就是从根节点出发一直搜索到叶子节点&#xff0c;然后想上返回。 这里简单说明一下&#xff1a;深搜的英文缩写是 dfs&#xff0c;下面定义深搜函数名我直接命名为 dfs 实战演练 …