当前位置: 首页 > news >正文

14.LeetCode 438 题解:滑动窗口+哈希表找所有字母异位词

目录

一、题目解析

二、讲解算法原理

1. 如何快速判断两个字符串是否是“异位词”?

2. 解决问题:滑动窗口 + 哈希表

三、解决问题(滑动窗口 + 哈希表流程)

四、优化:更新结果的判断条件

五、完整代码(Java)


一、题目解析

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

链接:438. 找到字符串中所有字母异位词 - 力扣(LeetCode)

题目描述:给定两个字符串sp,找到s中所有p的异位词的子串,返回这些子串的起始索引(不考虑答案输出的顺序)。

异位词:由相同字母重新排列形成的字符串(包括相同的字符串)。

示例 1

输入:s = "cbaebabacd",p = "abc"

输出:[0, 6]

解释:起始索引等于 0 的子串是"cba",它是"abc"的异位词;起始索引等于 6 的子串是"bac",它是"abc"的异位词。

示例 2

输入:s = "abab",p = "ab"

输出:[0, 1, 2]

二、讲解算法原理

1. 如何快速判断两个字符串是否是“异位词”?

利用哈希表。例如:

  • 字符串s1 = "aabca":统计每个字符出现次数 →a→3, b→1, c→1(记为hash1)。

  • 字符串s2 = "abaca":统计每个字符出现次数 →a→3, b→1, c→1(记为hash2)。

    hash1hash2完全相同,则两字符串是异位词。

2. 解决问题:滑动窗口 + 哈希表

核心思路:用滑动窗口维护s中与p长度相同的子串,用哈希表统计窗口内字符与p的字符频次,判断是否匹配。

三、解决问题(滑动窗口 + 哈希表流程)

  1. 初始化窗口:left = 0,right = 0

  2. 进窗口:将s[right]加入窗口,更新窗口字符的哈希表(hash2)。

  3. 判断窗口长度:若right - left + 1 > p.length(),则需要出窗口(移除s[left]),更新hash2

  4. 更新结果:检查hash2p的哈希表(hash1)是否匹配,若匹配则记录起始索引left

四、优化:更新结果的判断条件

利用变量count统计窗口中“有效字符”的个数(即窗口内字符频次 ≤p中对应字符频次的字符数量)。

  • 进窗口:进入字符后,若hash2[in] ≤ hash1[in],则count++(说明该字符是“有效”的)。

  • 出窗口:离开字符前,若hash2[out] ≤ hash1[out],则count--(说明该字符离开后,“有效”字符减少)。

  • 更新结果:当count == p.length()时,说明窗口内所有字符都“有效”,即找到异位词,记录left

五、完整代码(Java)

class Solution { public List<Integer> findAnagrams(String ss, String pp) { List<Integer> ret = new ArrayList<Integer>(); char[] s = ss.toCharArray(); char[] p = pp.toCharArray(); int[] hash1 = new int[26]; // 统计字符串 p 中每一个字符出现的个数 for (char ch : p) hash1[ch - 'a']++; int[] hash2 = new int[26]; // 统计窗口中每一个字符出现的个数 int m = p.length; for (int left = 0, right = 0, count = 0; right < s.length; right++) { char in = s[right]; if (++hash2[in - 'a'] <= hash1[in - 'a']) count++; // 进窗口 + 维护 count if (right - left + 1 > m) // 判断窗口长度是否超过 p 的长度 { char out = s[left++]; if (hash2[out - 'a']-- <= hash1[out - 'a']) count--; // 出窗口 + 维护 count } // 更新结果:当 count == m 时,说明窗口内是异位词 if (count == m) ret.add(left); } return ret; } }
http://www.zskr.cn/news/1458368.html

相关文章:

  • 手把手教你为S5P6818/FS4418开发板编译和烧写U-Boot(保姆级避坑指南)
  • 告别卡顿!用CGAL库5分钟搞定3D模型网格优化(附完整C++代码)
  • 2026年6月岗位外包公司推荐:TOP5专业评测用工成本控制案例价格 - 品牌推荐
  • 终极跨平台Java反编译工具Luyten:Windows、Mac、Linux系统高效适配完整指南
  • C语言性能优化封神指南:从CPU缓存到汇编调优,性能直接翻数倍
  • 别再死记硬背公式了!用Python脚本5分钟搞定异步FIFO深度计算(附代码)
  • 2026年6月北京管道疏通公司推荐:十大排名家庭防堵塞评测专业价格 - 品牌推荐
  • 高效研究周报:信息爆炸时代的知识管理利器
  • 传奇服务器CPU占用率飙升?从M2性能参数到怪物刷新策略的完整调优指南
  • 保姆级教程:给魔百盒CM311-5(GK6323芯片)刷入安卓9 TVBox固件,附固件下载与避坑指南
  • 从I2S到TDM:FPGA音频接口升级实战,轻松驱动8通道麦克风阵列
  • ComfyUI IPAdapter Plus完整指南:快速掌握多图像控制生成技术
  • 哪家北京管道疏通公司专业?2026年6月推荐TOP10市政管网清淤案例评测口碑特点 - 品牌推荐
  • WarcraftHelper深度技术解析:如何让经典魔兽争霸3在现代系统上焕发新生
  • 告别盲猜!用海德汉PWM21深度解析Endat信号:从位置值到信号质量百分百的完整诊断指南
  • Ai Skills CloakBrowser 零基础学习手册、Skills教程
  • 第08篇:音频与视频
  • 保姆级教程:在树莓派Ubuntu Mate 20.04上,用Mavros和QGC地面站搞定PX4飞控通信
  • 避开这些坑!三菱FX3U软元件实战配置中的5个常见误区与解决方案
  • 别再复制粘贴了!用ROS2 xacro宏定义,5分钟搞定差速机器人建模(附完整代码)
  • 从正则表达式到状态机:构建健壮的Recognizer类实现数据识别与解析
  • STM32CubeMX配置SDIO读写SD卡,我踩过的那些坑(F407+轮询/中断/DMA全解析)
  • 【2027最新】基于SpringBoot+Vue的乐享田园系统管理系统源码+MyBatis+MySQL
  • SpikGPT:单细胞注释的Transformer与脉冲神经网络融合框架
  • 微软研究院博士暑期学校:学术交流与职业发展的精英集训模式解析
  • 别再瞎调时序了!手把手教你用DC NXT TOPO模式搞定物理综合,从floorplan到compile_ultra全流程避坑
  • 深入I3C核心:动态地址分配中的48位临时ID与仲裁机制全解析
  • 3分钟搭建你的专属待办系统:跨平台桌面待办事项管理工具终极指南
  • FPGA图像处理第一步:避开BMP文件读写的那些坑(Verilog/SystemVerilog实战)
  • MATLAB版5G NOMA多用户BER仿真工具:含SIC解调、信道建模与可视化