438. 找到字符串中所有字母异位词
题目
给定两个字符串 s
和 p
,找到 s
中所有 p
的异位词的子串,返回这些子串的起始索引。不考虑答案输出的顺序。
异位词指由相同字母重排列形成的字符串(包括相同的字符串)。
示例 1:
- 输入:
s = "cbaebabacd"
,p = "abc"
- 输出:
[0, 6]
- 解释:
- 起始索引等于 0 的子串是
"cba"
,它是"abc"
的异位词。 - 起始索引等于 6 的子串是
"bac"
,它是"abc"
的异位词。
- 起始索引等于 0 的子串是
示例 2:
- 输入:
s = "abab"
,p = "ab"
- 输出:
[0, 1, 2]
- 解释:
- 起始索引等于 0 的子串是
"ab"
,它是"ab"
的异位词。 - 起始索引等于 1 的子串是
"ba"
,它是"ab"
的异位词。 - 起始索引等于 2 的子串是
"ab"
,它是"ab"
的异位词。
- 起始索引等于 0 的子串是
提示:
1 <= s.length, p.length <= 3 * 10^4
s
和p
仅包含小写字母
代码
完整代码
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>int* findAnagrams(char * s, char * p, int* returnSize) {int len_s = strlen(s);int len_p = strlen(p);int* result = (int*)malloc(len_s * sizeof(int));*returnSize = 0;if (len_s < len_p) {return result;}int hash_p[26] = {0};int hash_s[26] = {0};for (int i = 0; i < len_p; i++) {hash_p[p[i] - 'a']++;hash_s[s[i] - 'a']++;}for (int i = 0; i <= len_s - len_p; i++) {if (memcmp(hash_p, hash_s, 26 * sizeof(int)) == 0) {result[(*returnSize)++] = i;}if (i + len_p < len_s) {hash_s[s[i] - 'a']--;hash_s[s[i + len_p] - 'a']++;}}return result;
}
思路分析
- 使用滑动窗口在字符串
s
上检查长度为len_p
的子串是否是p
的异位词。 - 使用两个哈希表分别记录
p
和当前窗口内的字符频率。 - 滑动窗口每次移动时更新窗口内字符的频率,并与
p
的频率进行比较。
拆解分析
初始化哈希表
首先,我们需要记录 p
中每个字符的频率,同时记录 s
中前 len_p
个字符的频率。
int hash_p[26] = {0};
int hash_s[26] = {0};for (int i = 0; i < len_p; i++) {hash_p[p[i] - 'a']++;hash_s[s[i] - 'a']++;
}
滑动窗口检查
通过比较两个哈希表来判断当前窗口是否是 p
的异位词。如果是,则将当前窗口的起始索引加入结果。
for (int i = 0; i <= len_s - len_p; i++) {if (memcmp(hash_p, hash_s, 26 * sizeof(int)) == 0) {result[(*returnSize)++] = i;}if (i + len_p < len_s) {hash_s[s[i] - 'a']--;hash_s[s[i + len_p] - 'a']++;}
}
窗口移动
每次移动窗口时,更新窗口的字符频率,然后继续比较。
if (i + len_p < len_s) {hash_s[s[i] - 'a']--;hash_s[s[i + len_p] - 'a']++;
}
复杂度分析
- 时间复杂度:
O(n)
,其中n
是字符串s
的长度。初始化哈希表和滑动窗口移动都只需要遍历s
一次。 - 空间复杂度:
O(1)
,只需要两个固定大小的哈希表来记录字符频率。
结果
一题多解
双指针法
双指针法思路分析
使用双指针来维护一个滑动窗口,其中一个指针表示窗口的起始位置,另一个指针表示窗口的结束位置。通过计数器来记录当前窗口内的字符频率。
具体步骤:
- 初始化两个指针
left
和right
,以及一个计数器count
。 - 移动
right
指针扩展窗口,并更新计数器。 - 如果窗口大小等于
p
的长度,则检查是否是异位词。 - 如果窗口大小超过
p
的长度,则移动left
指针收缩窗口,并更新计数器。
双指针法复杂度分析
- 时间复杂度:
O(n)
,每个字符最多被访问两次(一次通过right
指针,一次通过left
指针)。 - 空间复杂度:
O(1)
,只需要固定大小的哈希表和计数器。
完整代码
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>int* findAnagrams(char * s, char * p, int* returnSize) {int len_s = strlen(s);int len_p = strlen(p);int* result = (int*)malloc(len_s * sizeof(int));*returnSize = 0;if (len_s < len_p) {return result;}int hash_p[26] = {0};for (int i = 0; i < len_p; i++) {hash_p[p[i] - 'a']++;}int left = 0, right = 0, count = len_p;while (right < len_s) {if (hash_p[s[right++] - 'a']-- > 0) {count--;}if (count == 0) {result[(*returnSize)++] = left;}if (right - left == len_p && hash_p[s[left++] - 'a']++ >= 0) {count++;}}return result;
}
拆解分析
初始化哈希表
记录 p
中每个字符的频率。
int hash_p[26] = {0};for (int i = 0; i < len_p; i++) {hash_p[p[i] - 'a']++;
}
移动右指针
移动 right
指针扩展窗口,并更新计数器。
int left = 0, right = 0, count = len_p;while (right < len_s) {if (hash_p[s[right++] - 'a']-- > 0) {count--;}
检查窗口
如果窗口大小等于 p
的长度,则检查是否是异位词。
if (count == 0) {result[(*returnSize)++] = left;
}
移动左指针
如果窗口大小超过 p
的长度,则移动 left
指针收缩窗口,并更新计数器。
if (right - left == len_p && hash_p[s[left++] - 'a']++ >= 0) {count++;
}
复杂度分析
- 时间复杂度:
O(n)
,每个字符最多被访问两次。 - 空间复杂度:
O(1)
,只需要固定大小的哈希表和计数器。
结果
相关文章:

438. 找到字符串中所有字母异位词
题目 给定两个字符串 s 和 p,找到 s 中所有 p 的异位词的子串,返回这些子串的起始索引。不考虑答案输出的顺序。 异位词指由相同字母重排列形成的字符串(包括相同的字符串)。 示例 1: 输入: s "cbaebabacd", p &q…...
【Qt 快速入门(三)】- Qt信号和槽
目录 Qt 快速入门(三)- Qt信号和槽Qt信号和槽详解信号和槽的基本概念信号槽连接 信号和槽的声明与定义连接信号和槽信号和槽的高级特性自动参数匹配信号与信号连接lambda 表达式作为槽自定义信号和槽 信号和槽的线程支持跨线程连接 信号和槽的生命周期管…...

Debain12 离线安装docker
官网教程:https://docs.docker.com/engine/install/debian/ 步骤 1. 解压 docker-deb.7z 安装包并上传Linux (资源在PC端文章顶部) 2. 安装 .deb 包 sudo dpkg -i ./containerd.io_<version>_<arch>.deb \./docker-ce_<vers…...

C++day5
思维导图 搭建一个货币的场景,创建一个名为 RMB 的类,该类具有整型私有成员变量 yuan(元)、jiao(角)和 fen(分),并且具有以下功能: (1)重载算术运算符 和 -…...
SHELL脚本学习(六) 呈现数据
一、标准文件描述符 linux系统会将每个对象当作文件来处理,包括输入和输出。linux用文件描述符来描述每个对象。文件描述符是一个非负整数,唯一会标识的是打开的文件。每个进程一次最多能打开9个文件描述符。处于特殊目的,bash shell保留了前…...

计算机网络:网络层 - IPv4数据报 ICMP协议
计算机网络:网络层 - IPv4数据报 & ICMP协议 IPv4数据报[版本 : 首部长度 : 区分服务 : 总长度][标识 : 标志 : 片偏移][生存时间 : 协议 : 首部检验和][可变部分 : 填充字段] ICMP协议 IPv4数据报 一个IPv4数据报,由首部和数据两部分组成ÿ…...

【需求设计】软件概要设计说明怎么写?概要设计说明书实际项目案例(63页Word直接套用)
软件概要设计说明书书写要点可以归纳为以下几个方面,以确保文档的准确性、完整性和可读性: 引言 目的:介绍编写该文档的目的、主要内容及目标读者。 背景:说明被开发软件的名称、项目提出者、开发者等背景信息。 需求概述…...

网络编程2----UDP简单客户端服务器的实现
首先我们要知道传输层提供的协议主要有两种,TCP协议和UDP协议,先来介绍一下它们的区别: 1、TCP是面向连接的,UDP是无连接的。 连接的本质是双方分别保存了对方的关键信息,而面向连接并不意味着数据一定能正常传输到对…...

服务架构的设计原则
墨菲定律与康威定律 在系统设计的时候,可以依据于墨菲定律 任何事情都没有表面上看起来那么简单所有的事情都会比你预计的时间长可能出错的事总会出错担心的某一个事情的发送,那么它就更有可能发生 在系统划分的时候,可以依据康威定律 系…...

Day 14:2938. 区分黑球和白球
Leetcode 2938. 区分黑球和白球 桌子上有 n 个球,每个球的颜色不是黑色,就是白色。 给你一个长度为 n 、下标从 0 开始的二进制字符串 s,其中 1 和 0 分别代表黑色和白色的球。 在每一步中,你可以选择两个相邻的球并交换它们。 返…...

部署YUM仓库及NFS共享服务
YUM概述 YUM 基于RPM包构建的软件更新机制 可以自动解决依赖关系 所有软件包由集中的YUM软件仓库提供 YUM只允许一个程序运行,虽然不影响命令的使用。DNF后,允许多个程序允许 YUM的配置文件在/etc/yum.conf 网络源(所有以repo为结尾都是源&am…...

web学习笔记(六十五)
目录 1. Hash模式和History模式 2. 导航守卫 3. 路由元信息 4.路由懒加载 1. Hash模式和History模式 Hash模式(哈希模式)和History模式(历史模式)是匹配路由的两种模式,一般默认配置Hash模式,可以在in…...

66. UE5 RPG 实现远程攻击武器配合角色攻击动画
在制作游戏中,我们制作远程攻击角色,他们一般会使用弓箭,弩,弹弓等武器来进行攻击。比如你使用弓箭时,如果角色在播放拉弓弦的动画,但是弓箭武器没有对应的表现,会显得很突兀。所以,…...
用 Python 编写自动发送每日电子邮件报告的脚本,并指导我如何进行设置
编写一个自动发送每日电子邮件报告的脚本涉及几个步骤。我们需要使用 Python 编写脚本,并使用一些库来发送电子邮件。下面是一个示例脚本和设置步骤。 第一步:安装必要的库 我们需要安装 smtplib 和 email 库。可以通过以下命令安装: pip …...

AI大模型的战场:通用与垂直的较量
目录 AI大模型的战场:通用与垂直的较量 1.引言 2.通用大模型的优势 2.1 概念 2.2 谷歌的BERT模型 2.3 OpenAI的GPT模型 2.4 微软的Visual Studio Code 2.5 结论 3.垂直大模型的崛起 3.1 概念 3.2 医疗影像分析的AI模型 3.3 自动驾驶领域的AI模型 3.4 金…...

单目标应用:基于人工原生动物优化器APO的微电网优化(MATLAB代码)
一、微电网模型介绍 微电网多目标优化调度模型简介_vmgpqv-CSDN博客 参考文献: [1]李兴莘,张靖,何宇,等.基于改进粒子群算法的微电网多目标优化调度[J].电力科学与工程, 2021, 37(3):7 二、人工原生动物优化算法求解微电网 2.1算法简介 人工原生动物优化器&am…...

USB端口管控软件|USB端口控制软件有哪些(小技巧)
USB端口管控软件成为了保障企业数据安全的重要手段。 本文将为您介绍几款知名的USB端口控制软件,并分享一些实用的小技巧,帮助您更好地管理US端口,确保企业信息安全。#usb接口# 一、USB端口控制软件推荐 1,域智盾 域智盾是一…...

CorelDRAW2024官方最新中文破解版Crack安装包网盘下载安装方法
在设计的世界里,软件工具的更新与升级总是令人瞩目的焦点。近期,CorelDRAW 2024中文版及其终身永久版的发布,以及中文破解版Crack的出现,再次掀起了设计圈的热潮。对于追求专业精确的设计师而言,了解这些版本的下载安装…...

Mysql学习(八)——多表查询
文章目录 五、多表查询5.1 多表关系5.2 多表查询概述5.3 内连接5.4 外连接5.5 自连接5.6 联合查询5.7子查询5.8 总结 五、多表查询 5.1 多表关系 概述:项目开发中,在进行数据库表结构设计时,会根据业务需求及业务模块之间的关系,…...

LabVIEW进行图像拼接的实现方法与优化
在工业检测和科研应用中,对于大尺寸物体的拍摄需要通过多次拍摄后进行图像拼接。LabVIEW 作为强大的图形化编程工具,能够实现图像拼接处理。本文将详细介绍LabVIEW进行图像拼接的实现方法、注意事项和提高效率的策略。 图像拼接的实现方法 1. 图像采集…...

IDEA运行Tomcat出现乱码问题解决汇总
最近正值期末周,有很多同学在写期末Java web作业时,运行tomcat出现乱码问题,经过多次解决与研究,我做了如下整理: 原因: IDEA本身编码与tomcat的编码与Windows编码不同导致,Windows 系统控制台…...

接口测试中缓存处理策略
在接口测试中,缓存处理策略是一个关键环节,直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性,避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明: 一、缓存处理的核…...

【Python】 -- 趣味代码 - 小恐龙游戏
文章目录 文章目录 00 小恐龙游戏程序设计框架代码结构和功能游戏流程总结01 小恐龙游戏程序设计02 百度网盘地址00 小恐龙游戏程序设计框架 这段代码是一个基于 Pygame 的简易跑酷游戏的完整实现,玩家控制一个角色(龙)躲避障碍物(仙人掌和乌鸦)。以下是代码的详细介绍:…...

微软PowerBI考试 PL300-选择 Power BI 模型框架【附练习数据】
微软PowerBI考试 PL300-选择 Power BI 模型框架 20 多年来,Microsoft 持续对企业商业智能 (BI) 进行大量投资。 Azure Analysis Services (AAS) 和 SQL Server Analysis Services (SSAS) 基于无数企业使用的成熟的 BI 数据建模技术。 同样的技术也是 Power BI 数据…...

边缘计算医疗风险自查APP开发方案
核心目标:在便携设备(智能手表/家用检测仪)部署轻量化疾病预测模型,实现低延迟、隐私安全的实时健康风险评估。 一、技术架构设计 #mermaid-svg-iuNaeeLK2YoFKfao {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg…...
IGP(Interior Gateway Protocol,内部网关协议)
IGP(Interior Gateway Protocol,内部网关协议) 是一种用于在一个自治系统(AS)内部传递路由信息的路由协议,主要用于在一个组织或机构的内部网络中决定数据包的最佳路径。与用于自治系统之间通信的 EGP&…...

LLMs 系列实操科普(1)
写在前面: 本期内容我们继续 Andrej Karpathy 的《How I use LLMs》讲座内容,原视频时长 ~130 分钟,以实操演示主流的一些 LLMs 的使用,由于涉及到实操,实际上并不适合以文字整理,但还是决定尽量整理一份笔…...

解读《网络安全法》最新修订,把握网络安全新趋势
《网络安全法》自2017年施行以来,在维护网络空间安全方面发挥了重要作用。但随着网络环境的日益复杂,网络攻击、数据泄露等事件频发,现行法律已难以完全适应新的风险挑战。 2025年3月28日,国家网信办会同相关部门起草了《网络安全…...
Vue 模板语句的数据来源
🧩 Vue 模板语句的数据来源:全方位解析 Vue 模板(<template> 部分)中的表达式、指令绑定(如 v-bind, v-on)和插值({{ }})都在一个特定的作用域内求值。这个作用域由当前 组件…...
DAY 26 函数专题1
函数定义与参数知识点回顾:1. 函数的定义2. 变量作用域:局部变量和全局变量3. 函数的参数类型:位置参数、默认参数、不定参数4. 传递参数的手段:关键词参数5 题目1:计算圆的面积 任务: 编写一…...