30-判断子序列

给定字符串 s 和 t ,判断 s 是否为 t 的子序列。

字符串的一个子序列是原始字符串删除一些(也可以不删除)字符而不改变剩余字符相对位置形成的新字符串。(例如,"ace""abcde"的一个子序列,而"aec"不是)。

进阶:

如果有大量输入的 S,称作 S1, S2, ... , Sk 其中 k >= 10亿,你需要依次检查它们是否为 T 的子序列。在这种情况下,你会怎样改变代码?

方法一:双指针法

这是最直观的方法,通过两个指针分别遍历字符串 s 和 t,逐个比较字符。

// 判断 s 是否为 t 的子序列
function isSubsequence(s: string, t: string): boolean {
    let i = 0; // 指向 s 的指针
    let j = 0; // 指向 t 的指针
    while (i < s.length && j < t.length) {
        if (s[i] === t[j]) {
            i++;
        }
        j++;
    }
    return i === s.length;
}

// 测试示例
let s1 = "ace";
let t1 = "abcde";
console.log(isSubsequence(s1, t1)); // 输出 true

let s2 = "aec";
let t2 = "abcde";
console.log(isSubsequence(s2, t2)); // 输出 false
复杂度分析
  • 时间复杂度:(O(n)),其中 n 是字符串 t 的长度,因为只需要遍历一次字符串 t
  • 空间复杂度:(O(1)),只使用了常数级的额外空间。

方法二:递归法

通过递归的方式来判断 s 是否为 t 的子序列。

function isSubsequenceRecursive(s: string, t: string): boolean {
    if (s.length === 0) {
        return true;
    }
    if (t.length === 0) {
        return false;
    }
    if (s[0] === t[0]) {
        return isSubsequenceRecursive(s.slice(1), t.slice(1));
    }
    return isSubsequenceRecursive(s, t.slice(1));
}

// 测试示例
let s3 = "ace";
let t3 = "abcde";
console.log(isSubsequenceRecursive(s3, t3)); // 输出 true

let s4 = "aec";
let t4 = "abcde";
console.log(isSubsequenceRecursive(s4, t4)); // 输出 false
复杂度分析
  • 时间复杂度:(O(n)),其中 n 是字符串 t 的长度。在最坏情况下,需要递归 n 次。
  • 空间复杂度:(O(n)),主要是递归调用栈的空间开销。

方法三:动态规划法

使用动态规划来解决这个问题,通过构建一个二维数组来记录子问题的解。

function isSubsequenceDP(s: string, t: string): boolean {
    let m = s.length;
    let n = t.length;
    let dp: boolean[][] = new Array(m + 1).fill(false).map(() => new Array(n + 1).fill(false));
    // 初始化
    for (let j = 0; j <= n; j++) {
        dp[0][j] = true;
    }
    for (let i = 1; i <= m; i++) {
        for (let j = 1; j <= n; j++) {
            if (s[i - 1] === t[j - 1]) {
                dp[i][j] = dp[i - 1][j - 1];
            } else {
                dp[i][j] = dp[i][j - 1];
            }
        }
    }
    return dp[m][n];
}

// 测试示例
let s5 = "ace";
let t5 = "abcde";
console.log(isSubsequenceDP(s5, t5)); // 输出 true

let s6 = "aec";
let t6 = "abcde";
console.log(isSubsequenceDP(s6, t6)); // 输出 false
复杂度分析
  • 时间复杂度:(O(m * n)),其中 m 是字符串 s 的长度,n 是字符串 t 的长度。需要填充一个 (m+1) 行 (n+1) 列的二维数组。
  • 空间复杂度:(O(m * n)),主要是二维数组的空间开销。

进阶:处理大量输入的情况

当有大量输入的 S((S_1, S_2, ... , S_k),(k >= 10) 亿)需要依次检查它们是否为 T 的子序列时,可以采用预处理 T 的方法。具体思路是记录 T 中每个字符出现的所有位置,然后对于每个 S 中的字符,使用二分查找来找到该字符在 T 中合适的位置。

import { bisectLeft } from '@ohos.bisect';

function isSubsequenceAdvanced(s: string, t: string): boolean {
    // 预处理 t,记录每个字符出现的所有位置
    let charIndexes: Map<string, number[]> = new Map();
    for (let i = 0; i < t.length; i++) {
        let char = t[i];
        if (!charIndexes.has(char)) {
            charIndexes.set(char, []);
        }
        charIndexes.get(char)!.push(i);
    }
    let prevIndex = -1;
    for (let char of s) {
        if (!charIndexes.has(char)) {
            return false;
        }
        let indexList = charIndexes.get(char)!;
        let index = bisectLeft(indexList, prevIndex + 1);
        if (index === indexList.length) {
            return false;
        }
        prevIndex = indexList[index];
    }
    return true;
}

// 测试示例
let s7 = "ace";
let t7 = "abcde";
console.log(isSubsequenceAdvanced(s7, t7)); // 输出 true

let s8 = "aec";
let t8 = "abcde";
console.log(isSubsequenceAdvanced(s8, t8)); // 输出 false
复杂度分析
  • 预处理时间复杂度:(O(m)),其中 m 是字符串 t 的长度。需要遍历一次字符串 t 来记录每个字符出现的位置。
  • 每个 S 的检查时间复杂度:(O(k log m)),其中 k 是字符串 S 的长度,m 是字符串 t 的长度。对于 S 中的每个字符,需要进行一次二分查找。
  • 空间复杂度:(O(m)),主要用于存储每个字符出现的位置。

通过这种方式,可以在处理大量输入时提高效率。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Linux】http 协议

目录 一、http协议 &#xff08;一&#xff09;http 协议的概念 &#xff08;二&#xff09;URL的组成 &#xff08;三&#xff09;urlencode 和 urldecode 二、http 的协议格式 &#xff08;一&#xff09;http 请求方法 &#xff08;二&#xff09;http 响应状态码 &a…

ACE协议学习1

在多核系统或复杂SoC&#xff08;System on Chip&#xff09;中&#xff0c;不同处理器核心或IP&#xff08;Intellectual Property&#xff09;模块之间需要保持数据的一致性。常用的是ACE协议or CHI。 先对ACE协议进行学习 ACE协议&#xff08;Advanced Microcontroller Bu…

ES-分词器安装与使用详解

安装分词器 windows环境&#xff0c;分词器有2种安装方式&#xff0c;1.直接命令安装&#xff1b;2.压缩包安装 IK分词器 查看ik分词器文档&#xff0c;找到安装方式介绍 文档链接&#xff1a; 方式1 elasticsearch-plugin install https://get.infini.cloud/elasticsearch/an…

FY-3D MWRI亮温绘制

1、FY-3D MWRI介绍 风云三号气象卫星&#xff08;FY-3&#xff09;是我国自行研制的第二代极轨气象卫星&#xff0c;其有效载荷覆 盖了紫外、可见光、红外、微波等频段&#xff0c;其目标是实现全球全天候、多光谱、三维定量 探测&#xff0c;为中期数值天气预报提供卫星观测数…

P8686 [蓝桥杯 2019 省 A] 修改数组--并查集 or Set--lower_bound()的解法!!!

P8686 [蓝桥杯 2019 省 A] 修改数组--并查集 题目 并查集解析代码【并查集解】 Set 解法解析lower_bound代码 题目 并查集解析 首先先让所有的f&#xff08;i&#xff09;i&#xff0c;即每个人最开始的祖先都是自己&#xff0c;然后就每一次都让轮到那个数的父亲1&#xff08…

docker启动jenkins,jenkins中调用docker

在jenkins中执行docker 思路 jenkins中安装docker客户端&#xff0c;使用第三方的docker(需要付费)。jenkins中安装docker客户端&#xff0c;另一个容器中安装docker服务&#xff0c; docker-in-docker&#xff0c;需要特权模式&#xff0c;或者第三方的工具。jenkins中什么都…

【GPT入门】第9课 思维树概念与原理

【GPT入门】第9课 思维树概念与原理 1.思维树概念与原理2. 算24游戏的方法 1.思维树概念与原理 思维树&#xff08;Tree of Thought&#xff0c;ToT &#xff09;是一种大模型推理框架&#xff0c;旨在解决更加复杂的多步骤推理任务&#xff0c;让大模型能够探索多种可能的解决…

时态--02--⼀般将来时

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 ⼀般将来时1.肯定句结构:主am/is/aregoing to do(v.原型) 2.否定句结构:主am/is/arenotgoing to do(v.原型) 3.一般疑问句结构:Am/Is/Are(提句⾸)主going to do (v.…

模型压缩技术(二),模型量化让模型“轻装上阵”

一、技术应用背景 在人工智能蓬勃发展的浪潮下&#xff0c;大模型在自然语言处理、计算机视觉等诸多领域大放异彩&#xff0c;像知名的GPT以及各类开源大语言模型&#xff0c;其规模与复杂度持续攀升。然而&#xff0c;这一发展也带来了挑战&#xff0c;模型越大&#xff0c;对…

swift-5-汇编分析闭包本质

一、枚举、结构体、类都定义方法 方法占用对象的内存么&#xff1f; 不占用 方法的本质就是函数 方法、函数都存放在代码段&#xff0c;因为方法都是公共的&#xff0c;不管 对象一还是对对象二调用都是一样的&#xff0c;所以放在代码段&#xff0c;但是每个对象的成员不一样所…

通义千问本地配置并实现微调

通义千问本地配置并实现微调 最小Qwen模型大小942mb from modelscope import snapshot_download model_dir = snapshot_download(“qwen/Qwen2.5-0.5B”, cache_dir=“./models2.5”) Qwen2.5-0.5B:942MB from modelscope import snapshot_download model_dir = snapshot_d…

< 自用文儿 > CertBot 申请 SSL 证书 使用 challenge 模式 避开防火墙的阻挡

环境&#xff1a; 腾讯 VPS 腾讯会向你销售 SSL &#xff0c; 这个本是免费的。CertBot 默认申请证书要用到 80 端口&#xff0c;会蹭边什么什么条款&#xff0c;备案法律来阻止80端口的通讯&#xff0c;没有网站也一样被阻拦。 通过腾讯买的域名&#xff1a; bestherbs.cn …

<建模软件安装教程1>Blender4.2系列

Blender4.2安装教程 0注意&#xff1a;Windows环境下安装 第一步&#xff0c;百度网盘提取安装包。百度网盘链接&#xff1a;通过网盘分享的文件&#xff1a;blender.zip 链接: https://pan.baidu.com/s/1OG0jMMtN0qWDSQ6z_rE-9w 提取码: 0309 --来自百度网盘超级会员v3的分…

SpringBoot统一响应类型3.1.1版本

前言&#xff1a; 通过实践而发现真理&#xff0c;又通过实践而证实真理和发展真理。从感性认识而能动地发展到理性认识&#xff0c;又从理性认识而能动地指导革命实践&#xff0c;改造主观世界和客观世界。实践、认识、再实践、再认识&#xff0c;这种形式&#xff0c;循环往…

如是APP:AI精准匹配需求,信用体系重构信任,双轮驱动打造无套路电商

如是APP:AI精准匹配需求,信用体系重构信任,双轮驱动打造无套路电商 2024年3月,一款结合AI导购与信用体系的电商平台——如是APP即将上线。如是APP通过AI对话帮助用户精准快速购物,并通过全维度信用体系实现产品信息透明化,旨在打造一个“信息对称”的电商平台,实现“无套路”的…

[SAP MM] 查看物料主数据的物料类型

创建物料主数据时&#xff0c;必须为物料分配物料类型&#xff0c;如原材料或半成品 在标准系统中&#xff0c;物料类型ROH(原材料)的所有物料都要从外部采购&#xff0c;而类型为NLAG(非库存物料)的物料则可从外部采购也可在内部生产 ① 特殊物料类型&#xff1a;NLAG 该物料…

Linux中部署DeepSeek,WSL(ubunt)中使用ollama部署deepseek-R1-7b

想在自己的Win11电脑上部署Linux的DeepSeek模型&#xff0c;但在网上一直没有找到合适的相应教程&#xff0c;自己查询各种网上资源&#xff0c;以及询问一些AI大模型后成功安装&#xff0c;并整理了以下步骤。仅作为个人学习笔记使用&#xff0c;由于本人对各方面知识掌握不足…

NoteGen是一款开源跨平台的 AI 笔记应用,专注于 recording 和 writing ,基于 Tauri 开发

一、软件介绍 文末提供程序和源码下载 NoteGen 是一款专注于记录和写作的跨平台 AI 笔记应用&#xff0c;基于 Tauri 开发。NoteGen 的核心理念是将记录、写作和 AI 结合使用&#xff0c;三者相辅相成。记录功能可以帮助用户快速捕捉和整理碎片化知识。整理功能是连接记录和写…

C++性能分析工具

C性能分析工具常用的三种。perf、gprof、pprof perf工具需要root权限&#xff0c;设置perf的suid位并不行&#xff0c;需要设置perf对应的内核参数。 perf使用&#xff1a; g -o example example.cpp -O2 # 运行程序并采样 sudo perf record -g ./example # 查看采样结果 sud…

【编译器】VSCODE搭建ESP32-C3

【编译器】VSCODE搭建ESP32-C3 文章目录 [TOC](文章目录) 前言一、下载配置二、编译三、烧录四、参考资料总结 前言 使用工具&#xff1a; 1. 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 一、下载配置 安装IDF&#xff0c;打开例程 二、编译 三…