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

LeetCode 438. 找到字符串中所有字母异位词 | 滑动窗口与字符计数数组解法

文章目录

    • 问题描述
    • 核心思路:滑动窗口 + 字符计数数组
      • 1. 字符计数数组
      • 2. 滑动窗口
    • 算法步骤
    • 完整代码实现
    • 复杂度分析
    • 关键点总结
    • 类似问题

问题描述

给定两个字符串 sp,要求找到 s 中所有是 p 的**字母异位词(Anagram)**的子串的起始索引。
字母异位词是指由相同字母重新排列形成的字符串(包含相同的字母且每个字母出现的次数相同)。
例如:

  • 输入:s = "cbaebabacd", p = "abc"
    输出:[0, 6]
    解释:s 中从索引 0 开始的 "cba" 和索引 6 开始的 "bac" 均为 "abc" 的异位词。

核心思路:滑动窗口 + 字符计数数组

1. 字符计数数组

  • 核心思想:通过固定长度的数组(长度26,对应26个小写字母)记录字符串中每个字符的出现次数。
  • 比较机制:若两个字符串的字符计数数组相同,则它们是字母异位词。

2. 滑动窗口

  • 窗口初始化:在 s 中初始化一个长度为 p.length() 的窗口。
  • 窗口滑动:每次向右移动窗口,移除左边界字符的计数,增加右边界字符的计数。
  • 实时比较:每次滑动后检查当前窗口的计数数组是否与 p 的计数数组一致。

算法步骤

  1. 边界处理:若 s 的长度小于 pp 为空,直接返回空列表。
  2. 初始化计数数组
    • pCount:统计 p 中每个字符的出现次数。
    • sCount:统计 s 中初始窗口(前 p.length() 个字符)的出现次数。
  3. 初始窗口检查:若初始窗口的计数与 p 一致,记录索引 0
  4. 滑动窗口遍历
    • 窗口每次右移一位,更新左边界字符的计数(减少)和右边界字符的计数(增加)。
    • 每次更新后检查计数数组是否匹配,若匹配则记录当前窗口的起始索引。

完整代码实现

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;public class Solution {public List<Integer> findAnagrams(String s, String p) {List<Integer> result = new ArrayList<>();int m = p.length();int n = s.length();// 边界条件处理if (m == 0 || n < m) {return result;}int[] pCount = new int[26]; // 记录p的字符计数int[] sCount = new int[26]; // 记录当前窗口的字符计数// 初始化p和s的初始窗口的字符计数for (int i = 0; i < m; i++) {pCount[p.charAt(i) - 'a']++;sCount[s.charAt(i) - 'a']++;}// 检查初始窗口是否匹配if (Arrays.equals(pCount, sCount)) {result.add(0);}// 滑动窗口:每次移动一位,更新sCount并检查for (int i = 1; i <= n - m; i++) {// 移除左边界字符的计数int leftChar = s.charAt(i - 1);sCount[leftChar - 'a']--;// 添加右边界字符的计数int rightChar = s.charAt(i + m - 1);sCount[rightChar - 'a']++;// 检查当前窗口是否匹配if (Arrays.equals(pCount, sCount)) {result.add(i);}}return result;}
}

复杂度分析

  • 时间复杂度O(n),其中 n 是字符串 s 的长度。
    滑动窗口遍历 s 需要 O(n),每次窗口操作(更新计数和比较)的时间为常数。
  • 空间复杂度O(1),使用固定长度的两个长度为26的数组。

关键点总结

  1. 字符计数数组:利用数组索引映射字符,快速统计字符出现次数。
  2. 滑动窗口优化:避免每次重新计算整个子串的计数,通过动态更新窗口边界字符的计数保证高效性。
  3. 边界处理:注意字符串长度不足时的直接返回逻辑。

类似问题

  • LeetCode 567. 字符串的排列:判断 s2 是否包含 s1 的排列。
  • LeetCode 76. 最小覆盖子串:寻找覆盖目标字符的最短子串。
http://www.xdnf.cn/news/7713.html

相关文章:

  • base算法
  • Web开发-Python应用Flask框架Jinja模版绑定路由参数传递页面解析SSTI注入
  • Baumer工业相机堡盟工业相机的工业视觉如何使用三色光进行字符识别检测
  • 第十六届C++B组easyQuestions
  • AI产品经理课程推荐
  • 2025ICPC南昌邀请赛-G
  • 【实验增效】5 μL/Test 高浓度液体试剂!Elabscience PE Anti-Mouse Ly6G抗体 简化流式细胞术流程
  • 【操作系统】进程同步问题——生产者-消费者问题
  • 【Git】远程操作
  • spring cloud gateway配置
  • 探索自定义地图样式,打造应用专属个性化地图
  • 《探索具身智能机器人视觉-运动映射模型的创新训练路径》
  • 中级网络工程师知识点8
  • Rocketmq Broker与队列关系,怎么存储的
  • AI语音合成平台:AnKo开启免费创作新时代!
  • 基于Telink 8258配合Wireshark抓包测试SIG Mesh的IV Index Update过程
  • Java基础 Day16
  • leetcode hot100:四、解题思路大全:滑动窗口(无重复字符的最长子串、找到字符串中所有字母异位词)、子串(和为k的子数组、)
  • Mysql刷题 day07
  • 苍穹外卖系统结构与功能报告
  • 飞致云旗下开源项目GitHub Star总数突破150,000个
  • 集成运算放大器知识汇总
  • js如何复制图片
  • 嘉立创EDA成图:原理图绘制以及PCB封装导出为.efoo文件
  • 用于管理共享内存的 C# 类 ShareMemory
  • Python 训练营打卡 Day 30
  • SpringBoot实现本地对象存储【minio、阿里云、七牛云】
  • Python-多进程编程 (multiprocessing 模块)
  • 101个α因子#6
  • P2670 [NOIP 2015 普及组] 扫雷游戏