【优选算法必刷100题】第014题(同向双指针:滑动窗口算法):找到字符串中所有字母异位词

【优选算法必刷100题】第014题(同向双指针:滑动窗口算法):找到字符串中所有字母异位词

 

🔥艾莉丝努力练剑:个人主页

专栏传送门:《C语言》《数据结构与算法》C/C++干货分享&学习过程记录Linux操作系统编程详解笔试/面试常见算法:从基础到进阶

⭐️为天地立心,为生民立命,为往圣继绝学,为万世开太平


🎬艾莉丝的简介:


🎬艾莉丝的算法专栏简介:


目录

014  找到字符串中所有字母异位词

1.1  算法思路:滑动窗口 + 哈希表

1.2  算法实现

1.2.1  第一次冲锋:失败告终

1.2.2  优化

1.2.3  简化代码

1.3  博主手记

结尾



014  找到字符串中所有字母异位词

力扣链接(任选一个链接做就可以了):

LCR 015. 找到字符串中所有字母异位词

438. 找到字符串中所有字母异位词

力扣题解链接(两个题目是一样的,博主就只挂438题的题解链接了):

滑动窗口+哈希表解决【找到字符串中所有字母异位词】问题

题目描述:

两道题是一模一样的,所以大家任选一个链接点过去做就可以了。

1.1  算法思路:滑动窗口 + 哈希表

(1)因为字符串p的异位词的长度一定与字符串p的长度相同,所以我们可以在字符串s中构
造一个长度为与字符串p的长度相同的滑动窗口,并在滑动中维护窗口中每种字母的数量;
(2)当窗口中每种字母的数量与字符串中每种字母的数量相同时,则说明当前窗口为字符串p的异位词;
(3)因此可以用两个大小为26的数组来模拟哈希表,一个来保存s中的子串每个字符出现的个数,另一个来保存p中每一个字符出现的个数。这样就能判断两个串是否是异位词。

这里的算法思路比较简略,大家可以去看【博主手记】的博主手绘过程,会更好理解!

1.2  算法实现

1.2.1  第一次冲锋:失败告终

代码演示如下——

//自己实现——失败 class Solution { public: vector<int> findAnagrams(string s, string p) { int hash1[30001] = { 0 }; int hash2[30001] = { 0 }; int ret = 0;//返回结果 int n = s.size(); int m = p.size(); //左右指针 for (int left = 0, right = 0; left < n - m + 1, right < n; left++, right++) { //进窗口 hash2[in]++; //判断 if (right - left + 1 > m) hash2[out]--; } //更新结果 ret = check(hash1, hash2); } return ret; };
为什么会失败呢?uu们可以帮博主分析一下吗?哪里出问题了?

1.2.2  优化

代码演示如下——

class Solution { public: vector<int> findAnagrams(string s, string p) { //返回结果 vector<int> ret; int hash1[26] = { 0 };//统计字符串p中每个字符出现的个数 for (auto ch : p)hash1[ch - 'a']++;//范围for int hash2[26] = { 0 };//统计滑动窗口中每一个字符出现的个数 int n = s.size(); int m = p.size(); //左右指针 for (int left = 0, right = 0, count = 0; right < n; right++) { char in = s[right]; //进窗口 hash2[in - 'a']++; if(hash2[in - 'a'] <= hash1[in - 'a']) count++; //这一步也可以优化,hash2[in - 'a']++;写进if判断里面 if (right - left + 1 > m)//判断 { char out = s[left++];//left要向右移动一位 if(hash2[out - 'a'] <= hash1[out -'a']) count--; hash2[out - 'a']--;//也可以优化到前面,变成if(hash2[out - 'a']-- <= hash1[out -'a']) count--; } //更新结果 if (count == m) ret.push_back(left); } return ret; } };
时间复杂度:O(n),空间复杂度:O(1)。

1.2.3  简化代码

逻辑已经对了,示例也能通过,接下来再看看代码还能不能再优化一下。我们发现其实这段代码还可以改进一下——合并两个操作:进窗口 + 维护 count、出窗口 + 维护 count——

代码演示如下——

class Solution { public: vector<int> findAnagrams(string s, string p) { //返回结果 vector<int> ret; int hash1[26] = { 0 };//统计字符串p中每个字符出现的个数 for (auto ch : p)hash1[ch - 'a']++;//范围for int hash2[26] = { 0 };//统计滑动窗口中每一个字符出现的个数 int n = s.size(); int m = p.size(); //左右指针 for (int left = 0, right = 0, count = 0; right < n; right++) { char in = s[right]; // //进窗口 // hash2[in - 'a']++; // if(hash2[in - 'a'] <= hash1[in - 'a']) count++; // //这一步也可以优化,hash2[in - 'a']++;写进if判断里面 if (++hash2[in - 'a'] <= hash1[in - 'a']) count++; // 进窗口 + 维护 count if (right - left + 1 > m)//判断 { char out = s[left++];//left要向右移动一位 if (hash2[out - 'a']-- <= hash1[out - 'a']) count--; // 出窗口 + 维护count // if(hash2[out - 'a'] <= hash1[out -'a']) count--; // hash2[out - 'a']--;//也可以优化到前面,变成if(hash2[out - 'a']-- <= hash1[out -'a']) count--; } //更新结果 if (count == m) ret.push_back(left); } return ret; } };
时间复杂度:O(n),空间复杂度:O(1)。

现在耗时的情况就已经优化不少了。

1.3  博主手记

本题整个的思路、算法原理、解题过程博主在纸上推导了一遍,大家可以参考一下手记的推导过程!最好做题的过程中自己也推导一遍!!!自己推导很重要!

这个手记前面的部分包括暴力解法、直接比较hash1 == hash2的解法这两个方法博主在本文中都没有演示,大家可以根据自己的理解来动手实操一下!

结尾

往期回顾:

【优选算法必刷100题】第013题(同向双指针:滑动窗口算法):水果成篮问题

结语:都看到这里啦!那请大佬不要忘记给博主来个“一键四连”哦!

🗡博主在这里放了一只小狗,大家看完了摸摸小狗放松一下吧!🗡

૮₍ ˶ ˊ ᴥ ˋ˶₎ა


Read more

【OpenClaw从入门到精通】第10篇:OpenClaw生产环境部署全攻略:性能优化+安全加固+监控运维(2026实测版)

【OpenClaw从入门到精通】第10篇:OpenClaw生产环境部署全攻略:性能优化+安全加固+监控运维(2026实测版)

摘要:本文聚焦OpenClaw从测试环境走向生产环境的核心痛点,围绕“性能优化、安全加固、监控运维”三大维度展开实操讲解。先明确生产环境硬件/系统选型标准,再通过硬件层资源管控、模型调度策略、缓存优化等手段提升响应速度(实测响应效率提升50%+);接着从网络、权限、数据三层构建安全防护体系,集成火山引擎安全方案拦截高危操作;最后落地TenacitOS可视化监控与Prometheus告警体系,配套完整故障排查清单和虚拟实战案例。全文所有配置、代码均经实测验证,兼顾新手入门实操性和进阶读者的生产级部署需求,帮助开发者真正实现OpenClaw从“能用”到“放心用”的跨越。 优质专栏欢迎订阅! 【DeepSeek深度应用】【Python高阶开发:AI自动化与数据工程实战】【YOLOv11工业级实战】 【机器视觉:C# + HALCON】【大模型微调实战:平民级微调技术全解】 【人工智能之深度学习】【AI 赋能:Python 人工智能应用实战】【数字孪生与仿真技术实战指南】 【AI工程化落地与YOLOv8/v9实战】【C#工业上位机高级应用:高并发通信+性能优化】 【Java生产级避坑指南:

By Ne0inhk
ARM Linux 驱动开发篇--- Linux 并发与竞争实验(互斥体实现 LED 设备互斥访问)--- Ubuntu20.04互斥体实验

ARM Linux 驱动开发篇--- Linux 并发与竞争实验(互斥体实现 LED 设备互斥访问)--- Ubuntu20.04互斥体实验

🎬 渡水无言:个人主页渡水无言 ❄专栏传送门: 《linux专栏》《嵌入式linux驱动开发》《linux系统移植专栏》 ❄专栏传送门: 《freertos专栏》《STM32 HAL库专栏》 ⭐️流水不争先,争的是滔滔不绝  📚博主简介:第二十届中国研究生电子设计竞赛全国二等奖 |国家奖学金 | 省级三好学生 | 省级优秀毕业生获得者 | ZEEKLOG新星杯TOP18 | 半导纵横专栏博主 | 211在读研究生 在这里主要分享自己学习的linux嵌入式领域知识;有分享错误或者不足的地方欢迎大佬指导,也欢迎各位大佬互相三连 目录 前言  一、实验基础说明 1.1、互斥体简介 1.2 本次实验设计思路 二、硬件原理分析(看过之前博客的可以忽略) 三、实验程序编写 3.1 互斥体 LED 驱动代码(mutex.c) 3.2.1、设备结构体定义(28-39

By Ne0inhk
Flutter for OpenHarmony:swagger_dart_code_generator 接口代码自动化生成的救星(OpenAPI/Swagger) 深度解析与鸿蒙适配指南

Flutter for OpenHarmony:swagger_dart_code_generator 接口代码自动化生成的救星(OpenAPI/Swagger) 深度解析与鸿蒙适配指南

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net 前言 后端工程师扔给你一个 Swagger (OpenAPI) 文档地址,你会怎么做? 1. 对着文档,手写 Dart Model 类(容易写错字段类型)。 2. 手写 Retrofit/Dio 的 API 接口定义(容易拼错 URL)。 3. 当后端修改了字段名,你对着报错修半天。 这是重复劳动的地狱。 swagger_dart_code_generator 可以将 Swagger (JSON/YAML) 文件直接转换为高质量的 Dart 代码,包括: * Model 类:支持 json_serializable,带 fromJson/

By Ne0inhk
Linux 开发别再卡壳!makefile/git/gdb 全流程实操 + 作业解析,新手看完直接用----《Hello Linux!》(5)

Linux 开发别再卡壳!makefile/git/gdb 全流程实操 + 作业解析,新手看完直接用----《Hello Linux!》(5)

文章目录 * 前言 * make/makefile * 文件的三个时间 * Linux第一个小程序-进度条 * 回车和换行 * 缓冲区 * 程序的代码展示 * git指令 * 关于gitee * Linux调试器-gdb使用 * 作业部分 前言 做 Linux 开发时,你是不是也遇到过这些 “卡脖子” 时刻?写 makefile 时,明明语法没错却报错,最后发现是依赖方法行没加 Tab;想提交代码到 gitee,记不清 git add/commit/push 的 “三板斧”,还得反复搜教程;用 gdb 调试程序,输了命令没反应,才想起编译时没加-g生成 debug 版本;甚至连写个进度条,都搞不懂\r和\n的区别,导致进度条乱跳…… 其实这些问题,

By Ne0inhk