LeetCode题练习与总结:判断子序列--392
一、题目描述
给定字符串 s 和 t ,判断 s 是否为 t 的子序列。
字符串的一个子序列是原始字符串删除一些(也可以不删除)字符而不改变剩余字符相对位置形成的新字符串。(例如,"ace"是"abcde"的一个子序列,而"aec"不是)。
进阶:
如果有大量输入的 S,称作 S1, S2, ... , Sk 其中 k >= 10亿,你需要依次检查它们是否为 T 的子序列。在这种情况下,你会怎样改变代码?
示例 1:
输入:s = "abc", t = "ahbgdc" 输出:true
示例 2:
输入:s = "axc", t = "ahbgdc" 输出:false
提示:
0 <= s.length <= 1000 <= t.length <= 10^4- 两个字符串都只由小写字符组成。
二、解题思路
这个问题可以通过双指针的方法来解决。我们定义两个指针,一个指向字符串s,另一个指向字符串t。我们遍历字符串t,每当我们遇到一个与s中当前字符相同的字符时,我们就移动s的指针。如果s的指针能够移动到s的末尾,那么s就是t的子序列。
(一) 基本实现
- 初始化两个指针
i和j,分别指向s和t的起始位置。 - 遍历字符串
t,如果t[j] == s[i],则i++。 - 如果
i等于s的长度,返回true。 - 如果遍历完
t后,i不等于s的长度,返回false。
(二) 进阶问题
对于进阶问题,如果需要检查大量的s字符串是否为t的子序列,我们可以预处理t来创建一个映射,记录t中每个字符出现的位置。这样,对于每个s,我们可以快速地检查它是否为t的子序列,而不需要每次都遍历t。
三、具体代码
以下是基本实现的Java代码:
class Solution {public boolean isSubsequence(String s, String t) {int i = 0, j = 0;while (i < s.length() && j < t.length()) {if (s.charAt(i) == t.charAt(j)) {i++;}j++;}return i == s.length();}
}
以下是进阶问题的预处理和检查方法的Java代码:
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;class Solution {Map<Character, List<Integer>> indexMap;public boolean isSubsequence(String s, String t) {// 预处理tpreprocess(t);// 检查s是否为t的子序列return checkSubsequence(s);}private void preprocess(String t) {indexMap = new HashMap<>();for (int i = 0; i < t.length(); i++) {char c = t.charAt(i);indexMap.computeIfAbsent(c, x -> new ArrayList<>()).add(i);}}private boolean checkSubsequence(String s) {int prevIndex = -1;for (char c : s.toCharArray()) {if (!indexMap.containsKey(c)) {return false;}List<Integer> indices = indexMap.get(c);int pos = binarySearch(indices, prevIndex);if (pos == -1) {return false;}prevIndex = indices.get(pos) + 1;}return true;}private int binarySearch(List<Integer> indices, int target) {int left = 0, right = indices.size() - 1;while (left <= right) {int mid = left + (right - left) / 2;if (indices.get(mid) > target) {right = mid - 1;} else {left = mid + 1;}}return left < indices.size() && indices.get(left) > target ? left : -1;}
}
这里的preprocess方法预处理了字符串t,checkSubsequence方法用于检查字符串s是否为t的子序列。binarySearch方法用于在预处理后的列表中找到第一个大于target的索引。
四、时间复杂度和空间复杂度
(一) 基本实现
1. 时间复杂度
代码的时间复杂度主要取决于字符串s和t的长度。
while循环的条件是i < s.length()和j < t.length(),这意味着循环会持续直到至少一个字符串被完全遍历。- 在循环内部,我们执行了常数时间的操作(比较字符和增加指针)。
因此,循环将执行O(s.length() + t.length())次。这是因为每次循环中,我们至少将j增加1,直到t被完全遍历,而i的增加则最多与s的长度相同。所以,时间复杂度是O(n + m),其中n是字符串t的长度,m是字符串s的长度。
2. 空间复杂度
代码的空间复杂度主要取决于除了输入字符串之外所使用的额外空间。
i和j是两个整型变量,它们占用的空间是常数,即O(1)。- 没有使用任何其他的数据结构,如数组、列表或哈希表。
因此,空间复杂度是O(1),因为无论输入字符串s和t的长度如何,使用的额外空间都不会改变。
(二) 进阶问题
1. 时间复杂度
代码的时间复杂度可以分为预处理阶段和检查子序列阶段。
(1) 预处理阶段
preprocess方法:- 遍历字符串
t,其长度为n。 - 对于每个字符
c,将其索引添加到对应的列表中,这是一个常数时间的操作。
- 遍历字符串
- 因此,预处理的时间复杂度为 O(n)。
(2) 检查子序列阶段
checkSubsequence方法:- 遍历字符串
s,其长度为m。 - 对于
s中的每个字符,我们执行以下操作:- 检查字符是否在
indexMap中,这是常数时间的操作。 - 使用
binarySearch方法在对应的索引列表中查找第一个大于prevIndex的位置。 binarySearch方法的时间复杂度为 O(log k),其中k是列表中元素的数量,对于每个字符c,k最多为n。
- 检查字符是否在
- 遍历字符串
- 因此,检查子序列的总时间复杂度为 O(m log n)。
综合两个阶段,总的时间复杂度为 O(n + m log n)。
2. 空间复杂度
indexMap:- 存储了字符串
t中每个字符的所有索引位置。 - 假设字符集大小为
C(对于小写字母,C为 26),在最坏情况下,indexMap可能包含n个条目,每个条目对应一个字符的索引列表。 - 每个列表的平均长度为
n / C,所以总的存储空间为 O(n)。
- 存储了字符串
binarySearch方法:- 使用了常数额外空间,即 O(1)。
因此,总的空间复杂度为 O(n)。
五、总结知识点
(一) 基本实现
-
类定义:
class Solution:定义了一个名为Solution的类。
-
方法定义:
public boolean isSubsequence(String s, String t):定义了一个公共方法isSubsequence,它接受两个字符串参数s和t,并返回一个布尔值。
-
变量声明与初始化:
int i = 0, j = 0;:声明并初始化了两个整型变量i和j,用于在字符串s和t中遍历。
-
循环结构:
while (i < s.length() && j < t.length()):使用while循环来遍历字符串s和t,直到至少一个字符串被完全遍历。
-
字符串操作:
s.charAt(i):使用charAt方法来获取字符串s中索引为i的字符。t.charAt(j):使用charAt方法来获取字符串t中索引为j的字符。
-
条件判断:
if (s.charAt(i) == t.charAt(j)):条件判断语句,用于检查字符串s和t在当前位置的字符是否相等。
-
变量自增:
i++:当条件满足时,i的值自增,表示在字符串s中找到了一个匹配的字符。j++:无论条件是否满足,j的值都会自增,表示在字符串t中移动到下一个字符。
-
方法返回值:
return i == s.length();:返回一个布尔值,表示字符串s是否完全在字符串t中找到,即s是否为t的子序列。
-
逻辑运算符:
&&:逻辑与运算符,用于在while循环中组合两个条件。
-
比较运算符:
==:用于比较两个值是否相等。
(二) 进阶问题
-
类定义:
class Solution:定义了一个名为Solution的类。
-
成员变量:
Map<Character, List<Integer>> indexMap:定义了一个成员变量indexMap,它是一个哈希表,键是字符,值是该字符在字符串中出现的索引列表。
-
构造方法:
- (无显式构造方法,但隐式有一个无参构造方法)。
-
方法定义:
public boolean isSubsequence(String s, String t):定义了一个公共方法isSubsequence,它接受两个字符串参数并返回一个布尔值。
-
预处理方法:
private void preprocess(String t):定义了一个私有方法preprocess,用于预处理字符串t并填充indexMap。
-
检查子序列方法:
private boolean checkSubsequence(String s):定义了一个私有方法checkSubsequence,用于检查字符串s是否为字符串t的子序列。
-
二分查找方法:
private int binarySearch(List<Integer> indices, int target):定义了一个私有方法binarySearch,用于在有序列表indices中查找第一个大于target的索引。
-
数据结构:
HashMap和ArrayList:使用了哈希表和动态数组来存储字符及其索引。
-
集合操作:
computeIfAbsent:在HashMap中,如果键不存在,则计算其值并插入到映射中。
-
循环结构:
for循环:用于遍历字符串t并填充indexMap。while循环:在binarySearch方法中用于实现二分查找。
-
字符操作:
char c = t.charAt(i):获取字符串t中第i个位置的字符。
-
逻辑判断:
if和else语句:用于条件判断。
-
递增和递减操作:
i++和j++:用于在字符串中移动指针。left++和right--:在二分查找中调整搜索范围。
-
返回值:
return语句:用于从方法中返回结果。
-
比较操作:
>和>=:用于比较整数。
以上就是解决这个问题的详细步骤,希望能够为各位提供启发和帮助。
相关文章:
LeetCode题练习与总结:判断子序列--392
一、题目描述 给定字符串 s 和 t ,判断 s 是否为 t 的子序列。 字符串的一个子序列是原始字符串删除一些(也可以不删除)字符而不改变剩余字符相对位置形成的新字符串。(例如,"ace"是"abcde"的一…...
json数据结构的转换
# json可用于赌徒与原件数据的转换(json以字符串的形式储存数据,在通过json进行两种语言的转换时,应先将数据类型转换成列表或字典,再由列表或字典转换成json字符串,最后由json字符串转换成另一种语言的列表或字典数据…...
mysql删除语句:@Update(“TRUNCATE TABLE employee“)讲解
这个 SQL 语句: TRUNCATE TABLE employee是一个 SQL DDL(数据定义语言) 操作,用于清空数据库表中的所有记录,但不会删除表结构(即列和索引等)。 逐部分解释: TRUNCATE:…...
如何修改浏览器指纹?
网络安全日益重要,我们的上网行为变得越来越容易被追踪和分析。其中,浏览器指纹就是一种强大的技术手段,它可以说是你上网的身份象征。 一、浏览器指纹是什么 浏览器指纹是网站和在线平台用来收集关于你的浏览器、设备和网络的详细信息的一…...
实现3D热力图
实现思路 首先是需要用canvas绘制一个2D的热力图,如果你还不会,请看json绘制热力图。使用Threejs中的canvas贴图,将贴图贴在PlaneGeometry平面上。使用着色器材质,更具json中的数据让平面模型 拔地而起。使用Threejs内置的TWEEN&…...
GEE ui界面实现:用户自画多边形, 按面积比例在多边形中自动生成样点,导出多边形和样点shp,以及删除上一组多边形和样点(有视频效果展示)
零、背景 这几天在选样点,发现GEE有强大的ui功能,于是应用在我的工作上。 下述代码实现了几个功能: ①用户可以自己勾勒多边形,随后程序会按面积比例在多边形中自动生成样点,同时根据改多边形的区域生成区域平均月N…...
React diff算法和Vue diff算法的主要区别
React和Vue都是流行的前端框架,它们各自实现了diff算法来优化虚拟DOM的更新过程。以下是React diff算法和Vue diff算法的主要区别: 1. diff策略 React diff算法: React的diff算法主要采用了同层级比较的策略,即它不会跨层级比较节…...
WSL 2 中 FastReport 与 FastCube 的设置方法与优化策略
软件开发人员长期以来一直在思考这个问题:“我们如何才能直接在 Windows 中运行 Linux 应用程序,而无需使用单独的虚拟机?” WSL 技术为这个问题提供了一个可能的答案。WSL 的历史始于 2016 年。当时,其实现涉及使用 Windows 内核…...
《线性代数》学习笔记
列向量无关 上个星期继续学线性代数,一个矩阵,如何判断它是的列向量有几个是线性无关呢?其实有好几个方法。第一个就是一个一个判断。 先选定一个,然后看下这两个,怎么看呢?如果两个列向量线性相关&#…...
Redis三种集群模式:主从模式、哨兵模式和Cluster模式
目录标题 1、背景及介绍2、 Redis 主从复制2.1、主从复制特点2.2、Redis主从复制原理2.3 PSYNC 工作原理2.3.1、启动或重连判断:2.3.2、第一次同步处理:2.3.3、断线重连处理:2.3.4、主节点响应2.3.5、全量同步触发条件:2.3.6、复制…...
CDH大数据平台部署
二、CDH简介 全称Cloudera’s Distribution Including Apache Hadoop。 hadoop的版本 (Apache、CDH、Hotonworks版本) 在公司中一般使用cdh多一些(收费的)、也有公司使用阿里云大数据平台、微软的大数据平台。 国内也有一些平台:星环大数…...
7.4、实验四:RIPv2 认证和触发式更新
源文件 一、引言:为什么要认证和采用触发式更新? 1. RIP v2 认证 RIP(Routing Information Protocol)版本 2 添加了认证功能,以提高网络的安全性。认证的作用主要包括以下几点: 防止路由欺骗 RIP v1 是不…...
【一步步开发AI运动小程序】二十一、如果将AI运动项目配置持久化到后端?
**说明:**本文所涉及的AI运动识别、计时、计数能力,都是基于云智「Ai运动识别引擎」实现。云智「Ai运动识别」插件识别引擎,可以为您的小程序或Uni APP赋于原生、本地、广覆盖、高性能的人体识别、姿态识别、10余种常见的运动计时、计数识别及…...
LED和QLED的区别
文章目录 1. 基础背光技术2. 量子点技术的引入3. 色彩表现4. 亮度和对比度5. 能效6. 寿命7. 价格总结 LED和 QLED都是基于液晶显示(LCD)技术的电视类型,但它们在显示技术、色彩表现和亮度方面有一些关键区别。以下是两者的详细区别ÿ…...
2024 年Postman 如何安装汉化中文版?
2024 年 Postman 的汉化中文版安装教程...
转化古老的Eclipse项目为使用gradle构建
很多古老的Java项目,是使用Eclipse作为IDE开发的。 那么,使用其它IDE的开发者,如何快速地进入这种古老项目的开发呢?或者说,一个Eclipse构建的古老项目,能不能转化成一个IDE无关的项目,进而所有…...
openGauss常见问题与故障处理(二)
2.网络故障定位手段 2.1 网络故障定位手段--常见网络故障引发的异常 在数据库正常工作的情况下,网络层对上层用户是透明的,但数据库在长期运行时,可能会由于各种原因导致出现网络异常或错误。 常见的因网络故障引发的异常有: 1>…...
Mysql 8迁移到达梦DM8遇到的报错
在实战迁移时,遇到两个报错。 一、列[tag]长度超出定义 在mysql中,tag字段的长度是varchar(20),在迁移到DM8后,这个长度不够用了。怎么解决? 在迁移过程中,“指定对象”时,选择转换。 在“列映…...
Android HandlerThread 基础
HandlerThread **一、HandlerThread的基本概念和用途**1. **目的**2. **与普通线程的区别** **二、HandlerThread的使用步骤**1. **创建HandlerThread对象并启动线程**2. **创建Handler并关联到HandlerThread的消息队列**3. **发送消息到HandlerThread的消息队列** **三、Handl…...
【智能算法应用】人工水母搜索算法求解二维路径规划问题
摘要 本文基于人工水母搜索算法(Jellyfish Search Algorithm, JSA),对二维路径规划问题进行了研究。JSA作为一种新兴的群体智能优化算法,模仿了水母在海洋中觅食和迁移的行为,以求解非线性、复杂的优化问题。实验结果…...
浏览器访问 AWS ECS 上部署的 Docker 容器(监听 80 端口)
✅ 一、ECS 服务配置 Dockerfile 确保监听 80 端口 EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]或 EXPOSE 80 CMD ["python3", "-m", "http.server", "80"]任务定义(Task Definition&…...
应用升级/灾备测试时使用guarantee 闪回点迅速回退
1.场景 应用要升级,当升级失败时,数据库回退到升级前. 要测试系统,测试完成后,数据库要回退到测试前。 相对于RMAN恢复需要很长时间, 数据库闪回只需要几分钟。 2.技术实现 数据库设置 2个db_recovery参数 创建guarantee闪回点,不需要开启数据库闪回。…...
Linux相关概念和易错知识点(42)(TCP的连接管理、可靠性、面临复杂网络的处理)
目录 1.TCP的连接管理机制(1)三次握手①握手过程②对握手过程的理解 (2)四次挥手(3)握手和挥手的触发(4)状态切换①挥手过程中状态的切换②握手过程中状态的切换 2.TCP的可靠性&…...
高频面试之3Zookeeper
高频面试之3Zookeeper 文章目录 高频面试之3Zookeeper3.1 常用命令3.2 选举机制3.3 Zookeeper符合法则中哪两个?3.4 Zookeeper脑裂3.5 Zookeeper用来干嘛了 3.1 常用命令 ls、get、create、delete、deleteall3.2 选举机制 半数机制(过半机制࿰…...
家政维修平台实战20:权限设计
目录 1 获取工人信息2 搭建工人入口3 权限判断总结 目前我们已经搭建好了基础的用户体系,主要是分成几个表,用户表我们是记录用户的基础信息,包括手机、昵称、头像。而工人和员工各有各的表。那么就有一个问题,不同的角色…...
Module Federation 和 Native Federation 的比较
前言 Module Federation 是 Webpack 5 引入的微前端架构方案,允许不同独立构建的应用在运行时动态共享模块。 Native Federation 是 Angular 官方基于 Module Federation 理念实现的专为 Angular 优化的微前端方案。 概念解析 Module Federation (模块联邦) Modul…...
【决胜公务员考试】求职OMG——见面课测验1
2025最新版!!!6.8截至答题,大家注意呀! 博主码字不易点个关注吧,祝期末顺利~~ 1.单选题(2分) 下列说法错误的是:( B ) A.选调生属于公务员系统 B.公务员属于事业编 C.选调生有基层锻炼的要求 D…...
大学生职业发展与就业创业指导教学评价
这里是引用 作为软工2203/2204班的学生,我们非常感谢您在《大学生职业发展与就业创业指导》课程中的悉心教导。这门课程对我们即将面临实习和就业的工科学生来说至关重要,而您认真负责的教学态度,让课程的每一部分都充满了实用价值。 尤其让我…...
USB Over IP专用硬件的5个特点
USB over IP技术通过将USB协议数据封装在标准TCP/IP网络数据包中,从根本上改变了USB连接。这允许客户端通过局域网或广域网远程访问和控制物理连接到服务器的USB设备(如专用硬件设备),从而消除了直接物理连接的需要。USB over IP的…...
iview框架主题色的应用
1.下载 less要使用3.0.0以下的版本 npm install less2.7.3 npm install less-loader4.0.52./src/config/theme.js文件 module.exports {yellow: {theme-color: #FDCE04},blue: {theme-color: #547CE7} }在sass中使用theme配置的颜色主题,无需引入,直接可…...
