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

【Hot100|9-LeetCode 438. 找到字符串中所有字母异位词】

这段代码是解决 LeetCode 438. 找到字符串中所有字母异位词 问题的固定大小滑动窗口 + 数组计数解法。核心目标是在字符串s中找到所有是字符串p字母异位词的子串,并返回这些子串的起始索引。字母异位词指字符种类和数量完全相同,但排列顺序不同的字符串。该解法时间复杂度为 O (m + n)(m 为p长度,n 为s长度),空间复杂度为 O (1)(因仅用两个固定大小的 26 位数组)。

注:代码存在一处小笔误(未定义变量n),需补充int n = s.length();才能正常运行,后续解析会修正该问题。

一、问题理解

问题要求

给定两个字符串sp,找到s中所有p的字母异位词的起始索引。

  • 示例:输入s = "cbaebabacd"p = "abc",输出[0,6]。因为s中索引 0 开始的"cba"和索引 6 开始的"bac"都是"abc"的字母异位词。

核心解题逻辑

字母异位词的核心特征是字符种类和对应数量完全一致,因此可通过统计字符频率判断两个字符串是否为异位词。结合固定大小的滑动窗口,在s中滑动出与p长度相同的子串,逐一比对频率,高效找到目标子串。

二、核心思路

  1. 字符频率统计:用两个长度为 26 的数组(对应 26 个小写英文字母)cntPcntS,分别记录p的字符频率和s当前滑动窗口内的字符频率。
  2. 固定窗口滑动:窗口大小固定为p的长度lenP。右指针遍历s时,不断将当前字符加入窗口并更新cntS;当窗口长度达到lenP后,每次右移都移除窗口最左侧的字符频率,保持窗口大小不变。
  3. 频率比对:当窗口长度等于lenP时,对比cntScntP。若两者相等,当前窗口对应的子串是p的异位词,记录窗口起始索引。

三、代码逐行解析(含修正)

先补充笔误修正后的完整代码,再逐行讲解:

java

运行

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;class Solution {public List<Integer> findAnagrams(String s, String p) {List<Integer> ans = new ArrayList<>();// 初始化两个计数数组,统计26个小写字母的出现次数int[] cntP = new int[26];int[] cntS = new int[26];int lenP = p.length();int n = s.length(); // 补充笔误,定义s的长度// 步骤1:统计字符串p的字符频率for (char c : p.toCharArray()) {// 字符c - 'a' 映射为0-25的索引(如'a'→0,'b'→1)cntP[c - 'a']++;}// 步骤2:右指针遍历s,维护固定大小的滑动窗口for (int right = 0; right < n; right++) {// 当前字符加入窗口,更新s的窗口频率数组cntS[s.charAt(right) - 'a']++;// 计算当前窗口的左边界:窗口大小固定为lenP,左边界 = 右边界 - lenP + 1int left = right - lenP + 1;// 窗口未达到p的长度(左边界为负),跳过后续比对if (left < 0) {continue;}// 步骤3:窗口大小达标,比对两个频率数组if (Arrays.equals(cntS, cntP)) {// 频率一致,记录当前窗口起始索引leftans.add(left);}// 步骤4:窗口右移前,移除左边界字符的频率(避免影响下一个窗口)cntS[s.charAt(left) - 'a']--;}return ans;}
}

关键代码拆解

  1. 初始化与p的频率统计

    • cntPcntS数组:因题目默认字符串为小写字母,用长度 26 的数组足够,通过c - 'a'将字符映射为 0 - 25 的索引,实现 O (1) 的频率更新。
    • 遍历p的字符,填充cntP,完成对p的字符频率记录。
  2. 右指针遍历与窗口维护

    • right从 0 开始遍历s,每遍历一个字符就将其频率加入cntS,相当于窗口向右扩展。
    • 计算leftleft = right - lenP + 1,这是固定窗口的核心,确保窗口长度始终等于lenP。例如lenP=3right=2时,left=0,窗口为[0,2],长度 3。
  3. 窗口有效性判断与结果记录

    • left < 0时,说明窗口还没达到p的长度(如right=1lenP=3时,left=-1),无需比对频率,直接跳过。
    • Arrays.equals(cntS, cntP):比对两个频率数组,若相等则当前窗口是p的异位词,将left加入结果列表。
  4. 窗口右移的预处理比对完成后,将cntSleft对应字符的频率减 1。这是因为下一轮right右移时,窗口会抛弃当前左边界的字符,确保下一个窗口的频率统计准确。

四、实例演示(直观理解过程)

以测试用例s = "cbaebabacd"p = "abc"为例(lenP=3cntPa:1b:1c:1,其余为 0):

步骤right遍历字符cntS 更新后left窗口内容频率是否匹配结果列表cntS 左边界减 1(操作)
10'c'c:1-2无(窗口不足)[]
21'b'c:1、b:1-1无(窗口不足)[]
32'a'c:1、b:1、a:10[0,2]:"cba"是(匹配 cntP)[0]减 'a'→a:0
43'e'c:1、b:1、e:11[1,3]:"bae"[0]减 'b'→b:0
54'b'c:1、b:1、e:12[2,4]:"aeb"[0]减 'a'→a:0
65'a'a:1、b:1、e:13[3,5]:"eba"[0]减 'e'→e:0
76'c'a:1、b:1、c:14[4,6]:"bac"[0,6]减 'b'→b:0
...........................

最终结果列表为[0,6],与预期一致。

五、关键细节与复杂度分析

1. 关键细节

  • 为什么用数组而非 HashMap:26 个小写字母的场景下,数组比 HashMap 更高效,无需哈希计算和处理哈希冲突,且Arrays.equals比对数组的时间为 O (26),属于常数时间。
  • 固定窗口的优势:相比可变滑动窗口,固定窗口无需复杂的左指针收缩逻辑,仅需在每次窗口达标后移除左边界字符频率,逻辑更简洁。
  • 边界处理left < 0的判断避免了窗口未达标时的无效比对,确保代码鲁棒性。

2. 复杂度分析

  • 时间复杂度:O (m + n)。遍历p统计频率耗时 O (m);遍历s耗时 O (n),每次遍历中的频率更新和数组比对均为 O (1)(数组比对固定 26 次),整体时间与字符串长度线性相关。
  • 空间复杂度:O (1)。两个计数数组均为固定长度 26,与输入字符串长度无关,无额外空间开销。

六、总结

该解法的核心是 **“固定滑动窗口 + 字符频率统计”**,精准利用字母异位词的频率特征,通过高效的数组计数和窗口维护,实现线性时间求解。这种思路不仅适用于本题,还可迁移到类似的字符串匹配问题(如判断子串是否包含目标字符集、统计符合字符频率要求的子串数量等),是处理字符串频率类问题的经典范式。

http://www.dtcms.com/a/587011.html

相关文章:

  • 自已电脑做网站服务器广州平面设计
  • 个人备案网站做购物网站可以不网站建设合同应注意什么
  • 百度网站关键词手机主题如何自己制作网站
  • 网站前端开发得会什么软件小学生有没有必要学编程
  • 建站公司一般用什么框架wordpress主题添加菜单
  • 一文理清 CMake、Make、Kbuild、GCC 关系:从基础到进阶的构建工具链全解析
  • 桂林旅游网官方网站上海网站建设学校与管理中专
  • 中药饮片采购是什么?其市场动态与发展趋势如何?
  • 有做网站赚钱的吗wordpress 外网无法访问
  • 2025nessus工具最新(10.8.3)安装破解
  • 能够做物理题的网站ssh wordpress
  • 远程教育网站建设方案中建装饰集团有限公司官网
  • Go Beego 简介
  • 商城网站哪个公司做的好处泰安创意网络公司
  • 云存储能用来做网站吗券优惠网站如何做
  • 自己做网站怎样挣钱当面付 wordpress
  • SIDI模型:压力诱导的审慎到直觉决策模拟
  • 大连网站制作网站珠海网站制作计划
  • 长沙企业网站建设优度创建iis网站
  • 咨询类网站建设个人怎样做旅游网站
  • RHCE Day3 DNS服务器
  • Android15 拓展安全策略SEPOLICY
  • 有创意的网站开发wordpress免插件生成地图
  • 百度如何创建网站深圳市建筑人才网
  • 耐克运动鞋网站建设规划书框架dedecms英文外贸网站企业模板
  • Java_Collections工具类
  • 重庆做网站letide杭州网站制作外包
  • seo品牌优化百度资源网站推广关键词排名网站开发课程设计
  • 专业网站建设市场金蝶直播
  • 网站建设可行性报告提供网站制作公司报价