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 <= 100
  • 0 <= t.length <= 10^4
  • 两个字符串都只由小写字符组成。

二、解题思路

这个问题可以通过双指针的方法来解决。我们定义两个指针,一个指向字符串s,另一个指向字符串t。我们遍历字符串t,每当我们遇到一个与s中当前字符相同的字符时,我们就移动s的指针。如果s的指针能够移动到s的末尾,那么s就是t的子序列。

(一) 基本实现
  • 初始化两个指针ij,分别指向st的起始位置。
  • 遍历字符串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方法预处理了字符串tcheckSubsequence方法用于检查字符串s是否为t的子序列。binarySearch方法用于在预处理后的列表中找到第一个大于target的索引。

四、时间复杂度和空间复杂度

(一) 基本实现
1. 时间复杂度

代码的时间复杂度主要取决于字符串st的长度。

  • 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. 空间复杂度

代码的空间复杂度主要取决于除了输入字符串之外所使用的额外空间。

  • ij是两个整型变量,它们占用的空间是常数,即O(1)
  • 没有使用任何其他的数据结构,如数组、列表或哈希表。

因此,空间复杂度是O(1),因为无论输入字符串st的长度如何,使用的额外空间都不会改变。

(二) 进阶问题
1. 时间复杂度

代码的时间复杂度可以分为预处理阶段和检查子序列阶段。

(1) 预处理阶段

  • preprocess 方法:
    • 遍历字符串 t,其长度为 n
    • 对于每个字符 c,将其索引添加到对应的列表中,这是一个常数时间的操作。
  • 因此,预处理的时间复杂度为 O(n)。

(2) 检查子序列阶段

  • checkSubsequence 方法:
    • 遍历字符串 s,其长度为 m
    • 对于 s 中的每个字符,我们执行以下操作:
      • 检查字符是否在 indexMap 中,这是常数时间的操作。
      • 使用 binarySearch 方法在对应的索引列表中查找第一个大于 prevIndex 的位置。
      • binarySearch 方法的时间复杂度为 O(log k),其中 k 是列表中元素的数量,对于每个字符 ck 最多为 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,它接受两个字符串参数st,并返回一个布尔值。
  • 变量声明与初始化

    • int i = 0, j = 0;:声明并初始化了两个整型变量ij,用于在字符串st中遍历。
  • 循环结构

    • while (i < s.length() && j < t.length()):使用while循环来遍历字符串st,直到至少一个字符串被完全遍历。
  • 字符串操作

    • s.charAt(i):使用charAt方法来获取字符串s中索引为i的字符。
    • t.charAt(j):使用charAt方法来获取字符串t中索引为j的字符。
  • 条件判断

    • if (s.charAt(i) == t.charAt(j)):条件判断语句,用于检查字符串st在当前位置的字符是否相等。
  • 变量自增

    • 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 语句:用于从方法中返回结果。
  • 比较操作

    • > 和 >=:用于比较整数。

以上就是解决这个问题的详细步骤,希望能够为各位提供启发和帮助。

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

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

相关文章

SpringBoot中的注解详解(二)

四、Param() &#xff08;mapper包 Dao层&#xff09; Param()&#xff1a; 功能&#xff1a; 用于在Mapper接口的方法参数上标记参数名称&#xff0c;以便在SQL语句中引用这些参数。 参数命名&#xff1a;在Mapper接口的方法参数上使用Param注解&#xff0c;可以为参数指定一…

一文1800字使用Jmeter进行http接口性能测试!

接口测试是测试系统组件间接口的一种测试。接口测试主要用于检测外部系统与系统之间以及内部各个子系统之间的交互点。测试的重点是要检查数据的交换&#xff0c;传递和控制管理过程&#xff0c;以及系统间的相互逻辑依赖关系等。 为什么要做接口测试&#xff1f; 越底层发现b…

新版flask pin码计算

Python debug pin码计算 需开启debug from flask import Flask app Flask(__name__) app.route("/") def index():return "Hello World" app.run(debugTrue) /console路由填入上方控制台的 PIN 码即可执行 Python 命令 Flask 的 PIN 码计算仅与 werkze…

比 PyTorch 更快的嵌入Python库:FastEmbed

嵌入生成 已成为自然语言处理&#xff08;NLP&#xff09;中不可或缺的一部分。 无论是智能推荐、文本相似度计算&#xff0c;还是聊天机器人&#xff0c;嵌入技术都扮演着重要角色。然而&#xff0c;我们常常会陷入繁重的库和庞大的模型中&#xff0c;耗时费力。 今天&#…

大模型部署解决方案之TorchServe+vLLM

TorchServe 是PyTorch 中将模型部署到生产环境的一个解决方案。它用HTTP 或HTTPS API 封装模型&#xff0c;可以处理多种任务&#xff0c;包括为部署模型分配workers、负责客户端和服务器之间通信等。 10月份发布的TorchServe 0.12 增加了对GenAI的支持&#xff0c;简化了大语…

博弈论(零和博弈)英文版题解

翻译&#xff1a; 假设我们有一个两人零和游戏&#xff0c;每个玩家有两种行动&#xff0c;行收益矩阵如下&#xff1a; 计算行和列玩家的最小最大最优策略以及游戏的价值。 X Y A a11 a12 B a21 a22 选项&#xff1a; 1. 行玩家&#x…

虚拟现实辅助工程技术应用于员工培训

你还在使用传统的入职方法吗&#xff0c;比如印刷指南、演示、课堂培训、讲座等等&#xff1f;是时候改变了。虚拟现实辅助工程技术提供了一个机会&#xff0c;可以让新员工的入职过程更高效、更有趣&#xff0c;也更令人兴奋。想象一下这样一个场景&#xff0c;新员工可以在第…

【健康警钟】胆已切除,生活调理有“胆”更精彩!必看指南!

在现代社会&#xff0c;由于生活习惯、饮食习惯等多种因素&#xff0c;一些人可能不得不面对胆囊切除手术。虽然手术能够有效解决胆囊结石、胆囊炎等问题&#xff0c;但胆囊作为人体的一部分&#xff0c;其功能的丧失无疑会对生活带来一定影响。那么&#xff0c;胆被割了之后&a…

windows NGIMX配置WebSocket反向代理

linux下 据说nginx是要有 stream的模块 Linux安装Nginx步骤之后续&#xff0c;带stream模块-CSDN博客 Nginx从1.3.13版本就开始支持WebSocket linux 下参考如下链接 配置 Nginx 反向代理 WebSocket - 哈喽哈喽111111 - 博客园 (cnblogs.com) SSL的配置参考 【Linux】采用…

三种读取配置文件的方式

在编写JDBC的util包以读取文件时&#xff0c;配置文件的位置会影响其读取方式。当前&#xff0c;默认配置文件直接放置在src文件夹下。 当读取.properties文件代码写法为&#xff1a; Properties props new Properties(); props.load(new FileInputStream("db.propertie…

丹摩征文活动|CogVideoX-2b:从安装到上线,轻松搞定全过程!

CogVideoX-2b&#xff1a;从安装到上线&#xff0c;轻松搞定全过程&#xff01; CogVideoX简介 CogVideoX的推出标志着视频生成技术的一次重大突破。过去&#xff0c;如何在保持高效的同时提升视频质量一直是一个难题&#xff0c;但CogVideoX 通过其先进的3D变分自编码器&…

工位管理优化:Spring Boot企业级系统

3系统分析 3.1可行性分析 通过对本企业级工位管理系统实行的目的初步调查和分析&#xff0c;提出可行性方案并对其一一进行论证。我们在这里主要从技术可行性、经济可行性、操作可行性等方面进行分析。 3.1.1技术可行性 本企业级工位管理系统采用SSM框架&#xff0c;JAVA作为开…

EMQX服务器的搭建,实现本地机和虚拟机之间的MQTT通信(详细教程)

前言 MQTT是一个基于客户端-服务器的消息发布/订阅传输协议。MQTT协议是轻量、简单、开放和易于实现的&#xff0c;这些特点使它适用范围非常广泛。 MQTT协议中有三种身份&#xff1a;发布者&#xff08;Publish&#xff09;、代理&#xff08;Broker&#xff09;&#xff08;…

Unity 热更新 之 一篇文章完全入门AssetBundle

本篇知识来源于unity官方手册以及siki学院的相关教程,链接如下,仅作学习分享 AssetBundle&#xff08;创建打包&#xff09;入门学习(基于Unity2017) - SiKi学院|SiKi学堂 - unity|u3d|虚幻|ue4/5|java|python|人工智能|视频教程|在线课程 目录 0.热更新是什么 1.AssetBundl…

图片怎么去水印?5个简单好用的图片去水印方法分享!

在日常生活中&#xff0c;图片水印的去除需求时常涌现&#xff0c;无论是出于个人兴趣还是工作需求&#xff0c;掌握去水印技巧能让我们更自由地利用图片资源。今天&#xff0c;我们为您精心挑选并介绍五种实用的图片去水印方法&#xff0c;让您轻松上手&#xff0c;即刻提升图…

半导体测试领域CP和KGD的区别

在半导体测试领域&#xff0c;KGD&#xff08;Known Good Die&#xff09;和 CP&#xff08;Chip Probing 或 Chip Test&#xff09;是两个重要的概念&#xff0c;它们分别代表了不同阶段的测试和验证过程。下面详细解释这两者的区别&#xff1a; CP&#xff08;Chip Probing …

人机融合智能中的系统与还原

一、人工智能中的系统与还原 人工智能&#xff08;AI&#xff09;作为现代科技的重要组成部分和应用涉及多个学领域&#xff0c;包括计算机科学、学、神经科学等人工智能的研究中系统的概念至关重要。系统不仅仅是简单的组件集合&#xff0c;更多地体现为各个部分之间的相互作用…

这可能是2024年看过最全最详细的Java面试八股文

前言: 本文收集整理了各大厂常见面试题 N 道&#xff0c;你想要的这里都有内容涵盖&#xff1a;Java、MyBatis、ZooKeeper、Dubbo、Elasticsearch、Memcached、Redis、MySQL、Spring、Spring Boot、Spring Cloud、RabbitMQ、Kafka、Linux 等技术栈&#xff0c;希望大家都能找到…

010_SSH_Sqlserver多媒体技术与应用课程网(学习资料+前台考试)_lwplus87

目 录 摘 要... III Abstract V 第1章 概述... 1 1.1 课题背景... 1 1.2 课题意义... 2 1.3开发工具及技术... 2 1.3.1 MyEclipse. 2 1.3.2 Tomcat 2 1.3.3 SqlServer 3 1.3.4 JSP. 3 1.4国内外现状... 4 第2章 可行性分析及总体设计原则... 5 2.1可行性分析…

免费数字孪生平台打造物流数据可视化大屏,助力消费跑出加速度

在当今快速发展的时代&#xff0c;物流行业已成为连接生产与消费的重要桥梁。2024年&#xff0c;中国物流行业再次刷新纪录&#xff0c;8月13日&#xff0c;我国第1000亿件快递已顺利产生&#xff0c;比2023年提前了71天&#xff0c;这一速度令人惊叹。而在这背后&#xff0c;物…