【面试经典150 | 双指针】判断子序列

文章目录

  • 写在前面
  • Tag
  • 题目来源
  • 题目解题
  • 解题思路
    • 方法一:双指针
    • 方法二:动态规划
  • 写在最后

写在前面

本专栏专注于分析与讲解【面试经典150】算法,两到三天更新一篇文章,欢迎催更……

专栏内容以分析题目为主,并附带一些对于本题涉及到的数据结构等内容进行回顾与总结,文章结构大致如下,部分内容会有增删:

  • Tag:介绍本题牵涉到的知识点、数据结构;
  • 题目来源:贴上题目的链接,方便大家查找题目并完成练习;
  • 题目解读:复述题目(确保自己真的理解题目意思),并强调一些题目重点信息;
  • 解题思路:介绍一些解题思路,每种解题思路包括思路讲解、实现代码以及复杂度分析;
  • 知识回忆:针对今天介绍的题目中的重点内容、数据结构进行回顾总结。

Tag

【双指针】【动态规划】【字符串】


题目来源

392. 判断子序列


题目解题

判断字符串 s 是不是字符串 t 的子序列,字符串的子序列指的是原字符串删除一些字符或者不删除字符但是不改变原来字符顺序而形成的新的字符串。


解题思路

方法一:双指针

我们使用两个指针 ij,初始化分别指向字符串 st 的初始位置。从前往后对 s[i]t[j] 进行匹配:

  • 如果 s[i] = t[j],则同时向右移动双指针;
  • 如果 s[i] != t[j],则只移动指向字符串字符的指针 j
  • 无论是否匹配,都需要移动 j 指针;
  • 最终,如果 i 移动到了字符串 s 的末尾,说明 st 的子序列。

实现代码

class Solution {
public:bool isSubsequence(string s, string t) {int i = 0, j = 0;int n = s.size(), m = t.size();while(i < n && j < m) {if(s[i] == t[j])++i;++j;}return i == n;}
};

复杂度分析

时间复杂度: O ( n + m ) O(n+m) O(n+m) n n ns 的长度, m m mt 的长度。无论匹配是否成功,都至少youyige有一个指针向右移动,两指针的移动总距离为 n + m n+m n+m

空间复杂度: O ( 1 ) O(1) O(1),仅仅使用了两个指针变量。

方法二:动态规划

方法一有可以进行优化的地方,在方法一中,我们需要枚举匹配 t 中的字符,如果 t 中不匹配的字符很长,我们会有大量的时间浪费在 t 中找下一个匹配的字符。

于是,我们可以先对字符串 t 进行预处理,记录从每个位置开始往后每一个字符第一次出现的位置。

状态

f[i][j] 表示字符串 t 中从位置 i 开始往后字符 j 第一次出现的位置。

状态转移

有如下的状态转移关系:

  • 如果 t[i] = j,那么 f[i][j] = i
  • 否则,f[i][j] = f[i+1][j]

根据以上转移关系,我们需要对字符串 t 从后往前进行动态规划。

base case

我们的边界状态为 f[m-1][...],我们置 f[m][...] = m,让 f[m-1][...] 正常转移,如果 f[i][j] = m,则表示从位置 i 开始往后不存在字符 j

我们通过 f 数组,可以快速定位到字符串 t 后面每一个第一次出现的字符(s 中的字符):

  • 如果 f[i][j] = m,则表示从字符串 t 位置 i 开始往后不存在 s 中的字符 j,则直接返回 false
  • 否则,更新 i,从新的位置开始定位 s 中的字符;
  • 如果一直没遇到 m,最后返回 true

方法二使用动态规划的方法对字符串 t 进行一次处理,可以大大提高匹配,也是 进阶 题目的一种解法。

实现代码

class Solution {
public:bool isSubsequence(string s, string t) {int n = s.size(), m = t.size();vector<vector<int>> f(m+1, vector<int>(26, 0));for (int i = 0; i < 26; ++i) {f[m][i] = m;}for (int i = m-1; i >= 0; --i) {for (int j = 0; j < 26; ++j) {if (t[i] == j + 'a') {f[i][j] = i;}else f[i][j] = f[i+1][j];}}int start = 0;for (int i = 0; i < n; ++i) {if (f[start][s[i] - 'a'] == m)return false;start = f[start][s[i] - 'a'] + 1;}return true;}
};  

复杂度分析

时间复杂度: O ( m × ∣ ∑ ∣ + n ) O(m \times \left| \sum \right| + n) O(m×+n) n n n 为字符串 s 的长度,m 为字符串 t 的长度, ∣ ∑ ∣ \left| \sum \right| 为字符集, ∣ ∑ ∣ = 26 \left| \sum \right| = 26 =26

空间复杂度: O ( m × ∣ ∑ ∣ ) O( m \times \left| \sum \right|) O(m×),使用的额外空间为对字符串 t 预处理所占用的空间。


写在最后

如果文章内容有任何错误或者您对文章有任何疑问,欢迎私信博主或者在评论区指出 💬💬💬。

如果大家有更优的时间、空间复杂度方法,欢迎评论区交流。

最后,感谢您的阅读,如果感到有所收获的话可以给博主点一个 👍 哦。

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

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

相关文章

Eclipse开源代码下载

当前插件开发&#xff0c;需要修改eclipse源码&#xff0c;如需要修改remote相关的代码&#xff0c;所以需要下载相关源码。网上大多资料都说的不清不楚的&#xff0c;也可能我太小白&#xff0c;不明白&#xff0c;反正就是折腾了一两天才感觉有点思路&#xff0c;改如何找源码…

virtualbox共享文件夹设置

宿主机是mac os&#xff0c;虚拟机是centos7.9。 一、virtualbox设置共享文件夹 选中虚拟机->设置->共享文件夹->点击号图标进行添加&#xff1a; 二、给虚拟机安装增强功能 打开virtualbox的虚拟机窗口界面&#xff0c;点击窗口顶部菜单中的设备->安装增强功能…

正则表达式学习和高级用法

以下所有的验证都在 在线验证 1. 起始符 / 正则表达式的起始符2. 限定符 匹配前面的子表达式**1次或多次**。例如&#xff0c;zo 能匹配 "zo" 以及"zoo"&#xff0c;但不能匹配 "z"。等价于 {1,}。 ? 匹配前面的子表达式**0次或1次**。例如…

Java基础入门·对存储文件File的相关操作

前言 File类获取的方法 getName() | getPath() File getAbsoluteFile() | File getParentFile() long length() File类遍历方法 IO流对象的分类 1.按照操作的文件类型分类 2.按照数据的流向分类 IO流对象的分类归纳 OutputStream 字节输出流写入文件的步骤 追加写入 F…

电路中VCC VDD VSS VEE GND的含义

在电路中&#xff0c;芯片引脚经常会出现VCC&#xff0c;VDD&#xff0c;VSS&#xff0c;VEE和GND这些标示。 其中VCC一般表示通用芯片的电源引脚&#xff0c;比如一些模拟运放的正电源引脚&#xff0c;74系列数字芯片的电源引脚&#xff0c;VCC一般接相应的正电源电压。 VDD一…

Mock数据:单元测试中的心灵鸡汤

在当今的软件开发领域&#xff0c;质量控制已经成为了一个不可或缺的环节。为了确保软件的稳定性和可靠性&#xff0c;开发者们投入了大量的时间和精力进行各种测试。其中&#xff0c;单元测试作为最基础的测试方法&#xff0c;其重要性不言而喻。然而&#xff0c;单元测试中的…

用于视觉检测的线扫远心镜头VS-LTC系列

VS-LTC 系列线扫远心镜头&#xff0c;近期已经新增 3.5倍及5倍型号 &#xff0c;支持大靶面芯片相机&#xff1b;适用于半导体&#xff0c;基板以及 Mini LED等行业的视觉检测。 在机器视觉产品资料查询平台&#xff0c;了解更多VS-LTC工业镜头的信息。 大靶面线扫远心镜头 …

swift 页面跳转

segue 故事板的屏幕之间导航 设置全局变量 退回操作 Optionals ??

vue项目打包_以生产环境prod模式打包_vue-cli-service 不是内部或外部命令,也不是可运行的程序---vue工作笔记0025

打开命令行: 首先执行npm install 不执行会报错: npm run build:prod --scripts-prepend-node-pathauto 然后再这样执行就是以生产环境模式打包了.

lv5 嵌入式开发-2 exec函数族

目录 1 进程 – exec函数族 1.1 exec函数族特点 1.2 进程 – execl / execlp使用方法 1.3 进程 – execv / execvp 2 进程 – system 3 exec族要点演示 掌握&#xff1a;exec函数族、system 1 进程 – exec函数族 执行程序&#xff0c;通孔ps -elf发现&#xff0c;父进…

【数据结构】二叉树链式结构的实现(三)

目录 一&#xff0c;二叉树的链式结构 二&#xff0c;二叉链的接口实现 1&#xff0c;二叉链的创建 2&#xff0c;接口函数 3&#xff0c;动态创立新结点 4&#xff0c;创建二叉树 5&#xff0c;前序遍历 6&#xff0c;中序遍历 7&#xff0c;后序遍历 三&#xff0c;结点个…

【Python】自动化办公之路:word自动化实战宝典!

文章目录 前言一、环境安装二、使用步骤1.引入库2.读入数据 Python-docx 编辑已存在文档win32com 将 doc 转为 docxwin32com 操作 word总结 前言 使用Python操作word大部分情况都是写操作&#xff0c;也有少许情况会用到读操作&#xff0c;在本次教程中都会进行讲解&#xff0…

Git(6)——GitHub

目录 一、简介 二、概要 三、注册 ​四、创建仓库 五、推送本地代码 六、拉取远端代码 一、简介 在Git&#xff08;5&#xff09;中&#xff0c;我们已经对Git分支的概念和用法有了一定了解&#xff0c;对于在本地进行代码版本管理&#xff0c;其实当前所学的东西基本已经…

C语言生成随机数、C++11按分布生成随机数学习

C语言生成随机数 如果只要产生随机数而不需要设定范围的话&#xff0c;只要用rand()就可以&#xff1b;rand()会返回一随机数值, 范围在0至RAND_MAX 间&#xff1b;RAND_MAX定义在stdlib.h, 其值为2147483647&#xff1b; 如果想要获取在一定范围内的数的话&#xff0c;直接做…

华为云HECS安装docker并安装mysql

1、运行安装指令 yum install docker都选择y&#xff0c;直到安装成功 2、查看是否安装成功 运行版本查看指令&#xff0c;显示docker版本&#xff0c;证明安装成功 docker --version 3、启用并运行docker 3.1启用docker指令 systemctl enable docker 3.2 运行docker指令…

AI绘图提示词Stable Diffusion Prompt 笔记

基础 提示词分为正向提示词&#xff08;positive prompt&#xff09;和反向提示词&#xff08;negative prompt&#xff09;&#xff0c;用来告诉AI哪些需要&#xff0c;哪些不需要词缀的权重默认值都是1&#xff0c;从左到右依次减弱&#xff0c;权重会影响画面生成结果。AI …

LLM预训练之RLHF(一):RLHF及其变种

在ChatGPT引领的大型语言模型时代&#xff0c;国内外的大模型呈现爆发式发展&#xff0c;尤其是以年初的LLaMA模型为首的开源大模型和最近百川智能的baichuan模型&#xff0c;但无一例外&#xff0c;都使用了「基于人类反馈的强化学习」&#xff08;RLHF&#xff09;来提升语言…

7.代理模式

1.UML 2.代码 #include <iostream> using namespace std;class Subject{ public:virtual void Request() 0; };class RealSubject:public Subject { public:virtual void Request(){cout << "RealSubject" << endl;} }; class Proxy:public Subj…

【结构型】代理模式(Proxy)

目录 代理模式(Proxy)适用场景代理模式实例代码&#xff08;Java&#xff09; 代理模式(Proxy) 为其他对象提供一种代理以控制对这个对象的访问。Proxy 模式适用于在需要比较通用和复杂的对象指针代替简单的指针的时候。 适用场景 远程代理 (Remote Proxy) 为一个对象在不同…

【Git】03-GitHub

文章目录 1. GitHub核心功能2. GitHub搜索项目3. GitHub搭建个人博客4. 团队项目创建5. git工作流选择5.1 需要考虑的因素5.2 主干开发5.2 Git Flow5.3 GitHub Flow5.4 GitLab Flow(带生产分支)5.4 GitLab Flow(带环境分支)5.4 GitLab Flow(带发布分支) 6. 分支集成策略7. 启用…