
java
class Solution {
public List<Integer> findAnagrams(String s, String p) {
List<Integer> result = new ArrayList<>();
int sLen = s.length();
int pLen = p.length();
//边界判断
if (sLen < pLen) {
return result;
}
//1.对p进行字符频率统计,并且计算p中字符个数
int pCount = 0;
Map<Character, Integer> pMap = new HashMap<>();
for (char c : p.toCharArray()) {
if (!pMap.containsKey(c)) {
pCount++;
}
pMap.put(c, pMap.getOrDefault(c, 0) + 1);
}
//2.求解第一个窗口中是否有异位词
int sCount = 0;
Map<Character, Integer> sMap = new HashMap<>();
for (int i = 0; i < pLen; i++) {
char ch = s.charAt(i);
if (pMap.containsKey(ch)) {
sMap.put(ch, sMap.getOrDefault(ch, 0) + 1);
if (sMap.get(ch).equals(pMap.get(ch))) {
sCount++;
}
}
}
if (pCount == sCount) {
result.add(0);
}
//3.滑动窗口遍历剩余字符
for (int i = pLen; i < sLen; i++) {
//3.1添加窗口右侧新字符
char rightChar = s.charAt(i);
if (pMap.containsKey(rightChar)) {
sMap.put(rightChar, sMap.getOrDefault(rightChar, 0) + 1);
if (sMap.get(rightChar).equals(pMap.get(rightChar))) {
sCount++;
}
}
//3.2移除窗口左侧旧字符
char leftChar = s.charAt(i - pLen);
if (pMap.containsKey(leftChar)) {
//3.2.1左侧旧字符移除后恰好有一个字符不匹配了,那么scount-1
if (sMap.get(leftChar).equals(pMap.get(leftChar))) {
sCount--;
}
//3.2.2左侧旧字符移除后这个词频为0,那么这个字符该从词典中移除,不为0则词频-1
int leftCount = sMap.get(leftChar);
if (leftCount == 1) {
sMap.remove(leftChar);
} else {
sMap.put(leftChar, leftCount - 1);
}
}
//3.3判断当前窗口的单词是否是异位词
if (sCount == pCount) {
result.add(i - pLen + 1);
}
}
//4.结果返回
return result;
}
}