数据结构与算法之字符串: LeetCode 567. 字符串的排列 (Ts版)

ops/2025/2/1 11:41:21/

字符串的排列

  • https://leetcode.cn/problems/permutation-in-string/description/

描述

  • 给你两个字符串 s1 和 s2 ,写一个函数来判断 s2 是否包含 s1 的 排列。如果是,返回 true ;否则,返回 false

  • 换句话说,s1 的排列之一是 s2 的 子串

示例 1

输入:s1 = "ab" s2 = "eidbaooo"
输出:true

解释:s2 包含 s1 的排列之一 (“ba”).

示例 2

输入:s1= "ab" s2 = "eidboaoo"
输出:false

提示

  • 1 <= s1.length, s2.length <= 1 0 4 10^4 104
  • s1 和 s2 仅包含小写字母

Typescript 版算法实现


1 ) 方案1:滑动窗口

function checkInclusion(s1: string, s2: string): boolean {const n: number = s1.length;const m: number = s2.length;// 如果 s1 的长度大于 s2,则不可能有排列包含在 s2 中if (n > m) {return false;}// 创建两个数组来存储 s1 和当前窗口中每个字符的频率const cnt1: number[] = new Array(26).fill(0);const cnt2: number[] = new Array(26).fill(0);// 统计 s1 和 s2 前 n 个字符的频率for (let i = 0; i < n; ++i) {cnt1[s1.charCodeAt(i) - 'a'.charCodeAt(0)]++;cnt2[s2.charCodeAt(i) - 'a'.charCodeAt(0)]++;}// 检查初始窗口是否匹配if (cnt1.toString() === cnt2.toString()) {return true;}// 滑动窗口遍历 s2 的其余部分for (let i = n; i < m; ++i) {// 更新当前窗口的频率计数cnt2[s2.charCodeAt(i) - 'a'.charCodeAt(0)]++;cnt2[s2.charCodeAt(i - n) - 'a'.charCodeAt(0)]--;// 检查当前窗口是否匹配if (cnt1.toString() === cnt2.toString()) {return true;}}return false;
}

2 ) 方案2:滑动窗口优化

function checkInclusion(s1: string, s2: string): boolean {const n: number = s1.length;const m: number = s2.length;// 如果 s1 的长度大于 s2,则不可能有排列包含在 s2 中if (n > m) {return false;}// 创建一个数组来存储字符频率差异const cnt: number[] = new Array(26).fill(0);// 统计 s1 和 s2 前 n 个字符的频率差异for (let i = 0; i < n; ++i) {--cnt[s1.charCodeAt(i) - 'a'.charCodeAt(0)];++cnt[s2.charCodeAt(i) - 'a'.charCodeAt(0)];}let diff: number = 0;for (const c of cnt) {if (c !== 0) {++diff;}}// 检查初始窗口是否匹配if (diff === 0) {return true;}// 滑动窗口遍历 s2 的其余部分for (let i = n; i < m; ++i) {const x: number = s2.charCodeAt(i) - 'a'.charCodeAt(0);const y: number = s2.charCodeAt(i - n) - 'a'.charCodeAt(0);if (x === y) {continue;}// 更新字符频率差异并调整 diffif (cnt[x] === 0) {++diff;}++cnt[x];if (cnt[x] === 0) {--diff;}if (cnt[y] === 0) {++diff;}--cnt[y];if (cnt[y] === 0) {--diff;}// 检查当前窗口是否匹配if (diff === 0) {return true;}}return false;
}

3 ) 方案3:双指针

function checkInclusion(s1: string, s2: string): boolean {const n: number = s1.length;const m: number = s2.length;// 如果 s1 的长度大于 s2,则不可能有排列包含在 s2 中if (n > m) {return false;}// 创建一个数组来存储字符频率差异const cnt: number[] = new Array(26).fill(0);// 统计 s1 的每个字符的频率差异for (let i = 0; i < n; ++i) {--cnt[s1.charCodeAt(i) - 'a'.charCodeAt(0)];}let left: number = 0;// 使用滑动窗口遍历 s2for (let right = 0; right < m; ++right) {const x: number = s2.charCodeAt(right) - 'a'.charCodeAt(0);++cnt[x];// 如果当前字符频率超出,调整左边界while (cnt[x] > 0) {--cnt[s2.charCodeAt(left) - 'a'.charCodeAt(0)];++left;}// 检查当前窗口大小是否与 s1 长度相等if (right - left + 1 === n) {return true;}}return false;
}

http://www.ppmy.cn/ops/154730.html

相关文章

HIVE介绍(五)_hive limit

注意: 1.Hive处理的数据存储在HDFS上 2.hive分析数据的底层处理逻辑是MapReduce 3.执行运行在Yarn上执行 Hive运行原理 Hive为什么要分区&#xff08;partitioned by&#xff09;? 随着系统运行时间越来越长,表的数据量不断增大,通过hive查询通常是"全表扫描"这样就…

Linux 多路转接select

Linux 多路转接select 1. select select() 是一种较老的多路转接IO接口&#xff0c;它有一定的缺陷导致它不是实现多路转接IO的最优选择&#xff0c;但 poll() 和 epoll() 都是较新版的Linux系统提供的&#xff0c;一些小型嵌入式设备的存储很小&#xff0c;只能使用老版本的…

【Flask】在Flask应用中使用Flask-Limiter进行简单CC攻击防御

前提条件 已经有一个Flask应用。已经安装了Flask和redis服务。 步骤1&#xff1a;安装Redis和Flask-Limiter 首先&#xff0c;需要安装redis和Flask-Limiter库。推荐在生产环境中使用Redis存储限流信息。 pip install redis Flask-Limiter Flask-Limiter会通过redis存储限…

2025年01月31日Github流行趋势

项目名称&#xff1a;Qwen2.5项目地址url&#xff1a;https://github.com/QwenLM/Qwen2.5项目语言&#xff1a;Shell历史star数&#xff1a;13199今日star数&#xff1a;459项目维护者&#xff1a;jklj077, JustinLin610, bug-orz, huybery, JianxinMa项目简介&#xff1a;Qwen…

DeepSeek模型:开启人工智能的新篇章

DeepSeek模型&#xff1a;开启人工智能的新篇章 在当今快速发展的技术浪潮中&#xff0c;人工智能&#xff08;AI&#xff09;已经成为了推动社会进步和创新的核心力量之一。而DeepSeek模型&#xff0c;作为AI领域的一颗璀璨明珠&#xff0c;正以其强大的功能和灵活的用法&…

前端八股CSS:盒模型、CSS权重、+与~选择器、z-index、水平垂直居中、左侧固定,右侧自适应、三栏均分布局

一、盒模型 题目&#xff1a;简述CSS的盒模型 答&#xff1a;盒模型有两种类型&#xff0c;可以通过box-sizing设置 1.标准盒模型&#xff08;content-box&#xff09;:默认值&#xff0c;宽度和高度只包含内容区域&#xff0c;不包含内边距、边框和外边距。 2.边框盒模型&a…

C++初阶 -- 初识STL和string类详细使用接口的教程(万字大章)

目录 一、STL 1.1 什么是STL 1.2 STL的版本 1.3 STL的六大组件 二、string类 2.1 string类的基本介绍 2.2 string类的默认成员函数 2.2.1 构造函数 2.2.2 析构函数 2.2.3 赋值运算符重载 2.3 string类对象的容量操作 2.3.1 size和length 2.3.2 capacity 2.3.3 r…

实验二 数据库的附加/分离、导入/导出与备份/还原

实验二 数据库的附加/分离、导入/导出与备份/还原 一、实验目的 1、理解备份的基本概念&#xff0c;掌握各种备份数据库的方法。 2、掌握如何从备份中还原数据库。 3、掌握数据库中各种数据的导入/导出。 4、掌握数据库的附加与分离&#xff0c;理解数据库的附加与分离的作用。…