代码随想录算法训练营第五十五天|392. 判断子序列、115. 不同的子序列

news2024/12/26 21:03:23

LeetCode 392. 判断子序列

链接:392. 判断子序列

双指针:

思路:

本题较容易,如果不用动态规划而是用双指针的办法思路会更加简单。首先两个指针fast,slow分别代表t,s的下标,快指针用于遍历长字符串t,慢指针遍历短字符串s。在遍历字符串之前可以先做一个判断,如果s长于t,则无论如何都无法在t中找到子序列s,直接返回false,如果s长度为0,则直接返回true。

然后是遍历的过程,快指针每次走一步,慢指针在当s[slow]等于t[fast]的时候才走一步,直到慢指针走完,则说明t存在子序列s,否则说明不存在。

代码:

class Solution {
public:
    bool isSubsequence(string s, string t) {
        if (t.size() < s.size())
           return false;
       int slow = 0, fast = 0;
        if (slow == s.size())
              return true;
        for (int fast = 0; fast < t.size();fast++)
        {
          if (t[fast] == s[slow])
          slow++;
          if (slow == s.size())
              return true;
}
        return false;
    }
};

动态规划:

思路:

相比于双指针,动态规划的思路要稍复杂些,但是仔细观察可以发现,本题和1143. 最长公共子序列思路十分相似,如果s和t的最长公共子串为s,则说明s一定是t的子串,照着这个思路,我们可以把最长公共子序列的代码直接照搬过来,最后加一个判断,如果dp[s.size()][t.size()] != s.size(),则说明s和t的最长公共子串不是s,s不为t的子序列,反之亦然。

另外在递推公式有一点需要注意,虽然不影响结果,但其实当s[i-1]不等于t[j-1]的时候,dp[i][j]不应该由dp[i-1][j]和dp[i][j-1]的最大值来决定,实际上dp[i][j]只可能来自dp[i][j-1],原因是当字符不匹配的时候我们不能跳过s的字符,而只能跳过t的字符,因为我们需要找到全部能匹配s的字符的t的子串,一旦跳过了会影响到dp的数值,但好在不影响本题的结果,只要我们最后做了dp数值是否等于s的长度的判断就不会出错。

代码:

class Solution {
public:
    bool isSubsequence(string s, string t) {
        // dp[i][j]表示长度为[0, i]的s和[0, j]的t的最长公共子序列长度
        vector<vector<int>> dp(s.size() + 1, vector<int>(t.size() + 1));
        for (int i = 1; i <= s.size(); i++)
            for (int j = 1; j <= t.size(); j++)
            {
                if (s[i-1] == t[j-1])
                    dp[i][j] = dp[i-1][j-1] + 1;
                else
                    dp[i][j] = max(dp[i-1][j], dp[i][j-1]);
            }
        if (dp[s.size()][t.size()] != s.size())
            return false;
        else
            return true;
    }
};

LeetCode 115. 不同的子序列

链接:115. 不同的子序列

思路:

这道题目难度一下子就上来了,我们还是按照动态规划的思路来解。首先定义下标:dp[i][j]表示字符串s中长度为i的子序列出现字符串t中长度为j的子序列的次数。根据定义,我们可以知道,当j为0时,不论s的长度为多少,出现长度为0的子序列的次数都为1,因为此时唯一的方法就是删除s中所有的字符,当然也包括s长度为0的情况,这时就不用删除。所以初始dp数组为dp[i][0] = 1,i的范围取[0, s.size()]。dp数组其余数均初始化为0。

接下来关键的地方是递推公式,当匹配字符的时候,有s[i-1]等于t[j-1]和不等于t[j-1]两种情况,先考虑简单一点的情况。

  1. s[i-1] != t[j-1]。这种时候的递推公式其实和上一题是一样的,当不相等的时候,跳过当前不匹配的s的字符串 ,令dp[i][j]等于去掉当前字符的上一个s的子字符串的长度i-1,也就是dp[i][j] = dp[i-1][j]。同样我们不能取dp[i][j-1],理由在上一题已经说过了,匹配的字符串t必须是完整的不能跳过。
  2. s[i-1] == t[j-1]。这种情况就相对复杂一些,首先当当前字符相等的时候,我们肯定可以匹配到当前字符,所以用s[i-1]去匹配t[j-1]时的方法数量为dp[i-1][j-1],但同时我们也可以不选取当前字符去匹配,而尝试用s[i]去匹配t[j-1],考虑这样一个例子:s = "abb", t = "ab",当我们匹配到第二个字符,也就是i和j等于2的时候,我们可以用s[1],也就是s的第一个"b",去匹配t[1],也可以用s[2],也就是s的第二个“b",去匹配t[1],这样一来就有两种结果数量了,前者的结果数量为dp[i-1][j],后者的结果数量为dp[i-1][j-1],那么最终递推公式为dp[i][j] = dp[i-1][j-1] + dp[i-1][j]。

为了方便理解,这里再贴一张dp数组的推导过程,图来自代码随想录

最后,选取最靠右下角的数 dp[s.size()][t.size()]返回即可。

代码:

class Solution {
public:
    int numDistinct(string s, string t) {
        // dp[i][j]表示以i-1下标结尾的s的子序列出现以j-1下标结尾的t的子字符串的次数
        vector<vector<uint64_t>> dp(s.size() + 1, vector<uint64_t>(t.size() + 1));
        // 初始化,当j为0时dp[i][0]为1
        for (int i = 0; i <= s.size(); i++)
            dp[i][0] = 1;
        for (int j = 1; j <= t.size(); j++)
            for (int i = 1; i <= s.size(); i++)
            {
                if (s[i-1] != t[j-1])
                    // 需要用t去匹配,所以j不能动
                    dp[i][j] = dp[i-1][j];
                else
                {
                    // 既可以用s[i-1]去匹配,也可以用s[i]去匹配
                    dp[i][j] = dp[i-1][j-1] + dp[i-1][j];
                }
            }
            return dp[s.size()][t.size()];
    }
};

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

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

相关文章

来浅谈一下:GraalVM下载、安装、特点、概括

文章目录前言一、GraaIVM是什么&#xff1f;二、GraaIVM优点三、安装GraaIVM1.GraaIVM Community版本简略2.下载3.解压4.配置变量4.1、JAVA_HOME改成graalvm的位置4.2、编辑path5、查看总结前言 GraaIVM High-performance runtime with new compiler optimizations to accele…

unity计算着色器

序 计算着色器&#xff0c;是什么&#xff1f;好像是并行计算的一个东西。 并行计算&#xff0c;挖矿&#xff1f;显卡&#xff1f; 那看来得先了解显卡&#xff0c;再了解计算着色器了。 认识显卡 显卡&#xff0c;小白&#xff0c;不懂。 显卡的印象&#xff0c;只是停…

批量修改文件名,图文教学,2分钟简单学会

​文件名称是文件的重要组成部分&#xff0c;在我们日常生活中&#xff0c;对文件进行命名&#xff0c;是经常使用到的一种功能。可是有时候需要重命名的文件实在是太多了咋办呢&#xff1f;有没有什么方法可以批量修改文件名&#xff1f; 本文将以图文教学的方式&#xff0c;…

为什么不建议在MySQL中使用 utf8?

MySQL 字符编码集中有两套 UTF-8 编码实现&#xff1a;utf8 和 utf8mb4。 如果使用 utf8 的话&#xff0c;存储 emoji 符号和一些比较复杂的汉字、繁体字就会出错。 为什么会这样呢&#xff1f;这篇文章可以从源头给你解答。 何为字符集&#xff1f; 字符是各种文字和符号的…

LPA-star算法(Lifelong Planning)及相关思考

一、LPA-star算法&#xff08;Lifelong Planning&#xff09;简介 LPA * ( Lifelong Planning 终身规划 A * )是一种基于A * 的增量启发式搜索算法&#xff0c;被用来处理动态环境下从给定起始点到给定目标点的最短路径问题&#xff0c;即起始点和目标点是固定的。 &#xff08…

图数据库知识点1:图数据库与关系型数据库区别

文章目录 前言一、图数据库区别于其他数据库的核心是什么&#xff1f;二、图数据库能解决哪些问题&#xff1f; 1.图的优势2.目前的图的实现方式及优劣3.图的技术趋势及优势小结总结前言 《图数据库知识点》系列有20讲&#xff0c;每一讲中会重点分享一个图数据库知识点&#…

什么是JVM?JVM的机制与JVM自动内存管理机制,如何进行优化

1. 什么是JVM&#xff1f; JVM是Java Virtual Machine&#xff08;Java虚拟机&#xff09;的缩写&#xff0c;JVM是一种用于计算设备的规范&#xff0c;它是一个虚构出来的计算机&#xff0c;是通过在实际的计算机上仿真模拟各种计算机功能来实现的。Java虚拟机包括一套字节码…

彻底搞懂MySql的B+Tree

1.什么是索引 官方定义&#xff1a;一种能为mysql提高查询效率的数据结构&#xff0c;索引是为了加速对表中数据行的检索而创建的一种分散存储的数据结构。好比如&#xff0c;一本书&#xff0c;你想找到自己想看的章节内容&#xff0c;直接查询目录就行。这里的目录就类似索引…

华为路由器升级系统文件

欢迎关注微信公众号【厦门微思网络】。http://www.xmws.cn 组网图形 组网需求 RouterA的管理网口与用户侧主机HostA相连。要求通过BootROM菜单下载系统文件至RouterA完成系统升级。 操作步骤 1.在PC端启动FTP Server服务。 2.用串口线连接并通过Console口登录设备。 3.重启设…

Java内存模型与线程(3)

文章目录4. Java与线程4.1 线程的实现4.2 Java线程调度4.3 状态转换4. Java与线程 并发不一定要依赖多线程&#xff08;如PHP中很常见的多进程并发&#xff09;&#xff0c;但是在Jva里面谈论并发&#xff0c;大多数都与线程脱不开关系。既然我们这本书探讨的话题是Java虚拟机…

一个系列涨粉47w,小红书内容创意卷出新高度

前有双11&#xff0c;后有世界杯&#xff0c;11月注定是热闹的。图源新红_流量分析_趋势查询在此情况下&#xff0c; 小红书内又涌现出哪些黑马博主&#xff1f;有多少品牌打造出了爆品&#xff1f;什么样的种草玩法才能成功出圈&#xff1f;我们将全面分析11月榜单&#xff0c…

java面向对象最全入门笔记

Java面向对象 什么是面向对象编程&#xff1f; 面向&#xff1a;找、拿。 对象&#xff1a;东西。 面向对象编程&#xff1a;找或者拿东西过来编程。 设计对象并使用 设计类&#xff0c;创建对象并使用 类是什么&#xff1f; 类&#xff08;设计图&#xff09;&#xff1…

Vue Cli安装和node-sass、less-loader、sass-loader安装

一、Vue Cli安装 CLI全程是Command-Line Interface&#xff0c;命令行界面&#xff0c;俗称脚手架&#xff0c;可以帮我们快速的创建vue项 Vue Cli的使用必须依赖node环境和webpack 管理员方式打开cmd进行安装&#xff0c;安装命令&#xff1a; npm i -g vue/cli 查看版本…

鸢尾花数据种类预测、分析与处理、scikit-learn数据集使用、seaborn作图及数据集的划分

一、鸢尾花种类预测 Iris数据集是常用的分类实验数据集&#xff0c;由Fisher, 1936收集整理&#xff0c;Iris也称鸢尾花卉数据集&#xff0c;是一类多重变量分析的数据集 鸢尾花数据集包含了 4个属性&#xff08;特征值&#xff09; Sepal.Length&#xff08;花萼长度&#…

Linux学习-69-Linux系统启动管理

16 Linux系统启动管理 Linux 系统的启动是不需要人为参与和控制的&#xff0c;只要选择开机&#xff0c;系统就会按照设定好的方式进行启动。不过&#xff0c;了解系统的启动有助于我们在系统出现问题时能够快速地修复 Linux 系统。在 CentOS 6.x 中&#xff0c;系统的启动过程…

NoSQLBooster for MongoDB 7.1.X

最智能的 MongoDB IDE NoSQLBooster 是 MongoDB v2.6-6.0 的跨平台 GUI 工具&#xff0c;它提供了内置的 MongoDB 脚本调试器MongoDB 脚本调试器、全面的服务器监控工具、链接流畅查询、SQL 查询、查询代码生成器、任务调度、ES2020 支持和高级智能感知体验。 嵌入式 MongoDB 外…

网络面试-0x17如何立即诶OSI模型和TCP/IP协议

OSI(Open System Interconnect) 开放式通信系统互连参考模型。 每一层实现各自的功能和协议&#xff0c;并完成与相邻层的接口通信。即每一层扮演固定的角色&#xff0c;互不打扰。 应用层 ⑦ 作用&#xff1a;通过应用程序间的交互来完成特定的网络应用。 定义了应用程序之间…

【ONE·R || R与C++混合编程简单介绍 】

总言 课堂演讲&#xff1a;R语言与CPP混合编程课后学习汇报。    文章目录总言1、汇报目的&#xff12;、RCPP2.1、简单介绍&#xff1a;2.2、简单使用演示&#xff1a;2.1.1、Rcpp包与RTools2.2.2、上手尝试1.0&#xff1a;一个hello world小程序。2.2.3、上手尝试2.0&#…

STC 51单片机57——矩阵键盘 基本原理演示

51单片机 矩阵键盘 基本原理演示 #include "reg51.h" sbit P11P1^1; sbit P14P1^4; sbit P20P2^0; sbit P21P2^1; void main(void) { P111;// Hight P140; //Low if(P111) P200; else P210; while(1); }

刷爆力扣之较大分组的位置

刷爆力扣之较大分组的位置 HELLO&#xff0c;各位看官大大好&#xff0c;我是阿呆 &#x1f648;&#x1f648;&#x1f648; 工作原因拖更些时日&#xff0c;今天阿呆继续记录下力扣刷题过程&#xff0c;收录在专栏算法中 &#x1f61c;&#x1f61c;&#x1f61c; 该专栏按照…