438. 找到字符串中所有字母异位词 - 力扣(LeetCode)
java
class Solution {
public List<Integer> findAnagrams(String s, String p) {
int sLen = s.length(), pLen = p.length();
if (sLen < pLen) {
return new ArrayList<Integer>();
}
List<Integer> ans = new ArrayList<Integer>();
int[] sCount = new int[26];
int[] pCount = new int[26];
for (int i = 0; i < pLen; ++i) {
++sCount[s.charAt(i) - 'a'];
++pCount[p.charAt(i) - 'a'];
}
// 第一个窗口判断:计数数组完全相等 = 字母异位词
if (Arrays.equals(sCount, pCount)) {
ans.add(0);
}
//窗口滑动,看下面的图即可理解
for (int i = 0; i < sLen - pLen; ++i) {
// 窗口左边界移出:左边字符计数-1
--sCount[s.charAt(i) - 'a'];
// 窗口右侧新增:新进来的字符计数+1
++sCount[s.charAt(i + pLen) - 'a'];
//字母种类及其各自数量相等即为异位词
if (Arrays.equals(sCount, pCount)) {
ans.add(i + 1);
}
}
return ans;
}
}
这里并没有传统的指针来表示窗口,而是用简单的字母数量来维护窗口
难点再讲
java
// sCount:滑动窗口内字母计数,26个小写字母
int[] sCount = new int[26];
// pCount:p字符串固定的字母计数,相当于对比模板
int[] pCount = new int[26];
这两个数组,就是用来存「每个字母出现了多少次」的统计表,因为只有小写 a-z,刚好 26 个,所以开长度 26 的数组
下标映射规则
字符 - 'a'(ASCII码从a开始)
'a'-'a' → 0'b'-'a' → 1- ......
'z'-'a' → 25
统计当前窗口里,s/p的子串各个字母有几个

java
++sCount[s.charAt(i) - 'a'];
s.charAt(i)拿到字符串s下标i位置的字符,比如字符是'b's.charAt(i) - 'a'``'b' - 'a' = 1,得到数组下标1sCount[1]就是计数数组里,b 字母对应的计数器格子++sCount[...]前置自增,等价于:这个格子里的数字 + 1
即sCount某字母 ++
窗口滑动图理解例子:
第一轮循环

第二轮循环
