滑动数组
如何在面试时快速想出思路?
- 最重要的:
Arrays.equals(sCount, pCount) - 使用两个数组,一个窗口数组
sCount,保存滑动时窗口里的字母。另一个是比较数组pCount,也就是p。 sCount是int数组,指针在s上滑动时,将所指字母映射到数组下标,并++。pCount也是int数组,保存p的字母,在整个算法过程保持不变,唯一的作用是与sCount比较是否相同。
如何滑动?
- 由于滑动时需要丢弃窗口的第一个字母,并加入下一个字母,因此需要分两次
for循环。第一次下标为0作为窗口首字母;第二次丢弃0,下标为1作为窗口首字母。
如何快速确定丢弃的字母区间和加入的字母区间?
- 写代码时,想象一个容量为
3的窗口,如下图,并放在s的最后,窗口前的字母都是丢弃区间,也就是i = [0, sLen - pLen)。 - 挪到下标为
1起始的窗口(此时i为0,因为要丢弃0),窗口第三个字母到s最后一个字母都是加入区间,也就是i + pLen。
class Solution {
public List<Integer> findAnagrams(String s, String p) {
int sLen = s.length();
int pLen = p.length();
List<Integer> res = new ArrayList<>();
if (sLen < pLen) {
return res;
}
int[] sCount = new int[26];
int[] pCount = new int[26];
char[] sArray = s.toCharArray();
char[] pArray = p.toCharArray();
for (int i = 0; i < pLen; i++) {
++sCount[sArray[i] - 'a'];
++pCount[pArray[i] - 'a'];
}
if (Arrays.equals(sCount, pCount)) {
res.add(0);
}
for (int i = 0; i < sLen - pLen; i++) {
--sCount[sArray[i] - 'a'];
++sCount[sArray[i + pLen] - 'a'];
if (Arrays.equals(sCount, pCount)) {
res.add(i + 1);
}
}
return res;
}
}