【暴力】用数组统计p中各个字母的出现次数,从头到尾匹配,相当于一个变长带限制的滑动窗口,O(n^2)的时间复杂度,勉强能过。
class Solution {
public List<Integer> findAnagrams(String s, String p) {
List<Integer> ans = new ArrayList();
int m = s.length(), n = p.length(), l = m - n, j;
int[] cnt = new int[26];
for(var i = 0; i < n; i++) cnt[p.charAt(i) - 'a']++;
for(var i = 0; i <= l; i++){
boolean flag = true;
int[] tmp = cnt.clone();
for(j = 0; j < n; j++){
char c = s.charAt(i + j);
if(tmp[c - 'a'] == 0){
flag = false; break;
}else{
tmp[c - 'a']--;
}
}
if(flag) ans.add(i);
}
return ans;
}
}
【滑动窗口】 定长滑动窗口,统计p长度的窗口内字符的个数,每次移动时把前面字符去掉,再加上后面的字符,与p中字符个数进行比对,时间复杂度降到O(n*26)
class Solution {
// 滑动窗口 1:28
public List<Integer> findAnagrams(String s, String p) {
int m = s.length(), n = p.length(), l = m - n;
int[] cnt = new int[26], wd = new int[26];
List<Integer> ans = new ArrayList();
if(m < n) return ans;
for(var i = 0; i < n; i++) cnt[p.charAt(i) - 'a']++;
for(var i = 0; i < n; i++) wd[s.charAt(i) - 'a']++;
if(Arrays.equals(cnt, wd)) ans.add(0);
for(var i = n; i < m; i++){
wd[s.charAt(i - n) - 'a']--;
wd[s.charAt(i) - 'a']++;
if(Arrays.equals(cnt, wd)) ans.add(i - n + 1);
}
return ans;
}
}