1. 问题理解与解法概述
今天想和大家分享一道力扣经典字符串处理题目——438. 找到字符串中所有字母异位词。这道题看似简单,但蕴含着滑动窗口和字符统计的精妙技巧。我在实际解题过程中踩过不少坑,也总结出了一些优化心得,希望能帮助到正在刷题的你。
1.1 什么是字母异位词?
字母异位词(Anagram)是指由相同字母重新排列组合形成的不同单词或短语。比如"listen"和"silent"就是一组典型的字母异位词。在本题中,我们需要在字符串s中找到所有与p构成字母异位词的子串,并返回它们的起始索引。
注意:字母异位词不仅要求字符种类相同,每个字符的出现次数也必须完全一致。例如"aab"和"abb"就不是字母异位词。
1.2 暴力解法的问题
最直观的解法是枚举s中所有长度为len(p)的子串,然后逐个检查是否为p的字母异位词。这种方法虽然直接,但时间复杂度高达O(n×m)(n为s长度,m为p长度),当字符串较长时(比如n=10^5),这种解法显然无法接受。
我在最初尝试时就用这种方法,结果在力扣的大数据测试用例上直接超时。这促使我开始思考更高效的解决方案。
1.3 滑动窗口的优化思路
滑动窗口(Sliding Window)是处理子串/子数组问题的利器。对于本题,由于我们要找的是固定长度(len(p))的子串,因此可以使用固定大小的滑动窗口:
- 初始化窗口大小为len(p)
- 窗口从s的起始位置开始滑动
- 每次滑动时,只关注"离开窗口"和"进入窗口"的字符
- 维护一个实时更新的字符频次统计
这种方法将时间复杂度降到了O(n),因为每个字符最多被处理两次(进入和离开窗口各一次)。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 核心算法实现细节
2.1 数组计数的选择
在处理小写字母统计问题时,使用长度为26的数组通常比哈希表更高效。原因有三:
- 数组的访问时间是O(1),且常数因子更小
- 可以直接用==操作符比较两个数组是否相同
- 不需要处理哈希冲突等问题
python复制# 初始化频次数组
p_count = [0] * 26
for char in p:
p_count[ord(char) - ord('a')] += 1
提示:ord(char) - ord('a')是将小写
