采用滑动窗口方法求解
题目描述
给定一个字符串 s 和一个非空字符串 p,找到 s 中所有是 p 的字母异位词的子串,返回这些子串的起始索引。
字符串只包含小写英文字母,并且字符串 s 和 p 的长度都不超过 20100。
说明:
字母异位词指字母相同,但排列不同的字符串。
不考虑答案输出的顺序。
变量及其初始化:
// hash 记录p中字母及出现次数
int [] hash = new int[26];
for(char c : p.toCharArray()) char[c-'a']++;
//使用左右两个index记录当前滑动窗口的左边和右边下标
int left = 0, right = 0;
//count 记录 p字符串的长度
int count = p.length();
思路:
1、窗口移动(left不变,right右移),若新增的窗口的元素在p中,则count–,表示p中一个元素加入窗口中。
2、若窗口中包含count个元素,则记录left
3、若窗口中的元素个数大于p.length(),则判断left指向的元素是否为p中元素
3.1:若是:count++(即,left++后,一个p中元素从窗口移除);
3.2:否,则不做改变。
完整代码
public List<Integer> findAnagrams(String s, String p) {
List<Integer> res = new ArrayList<Integer>();
if(s==null||p==null||s.length()<p.length()) return res;
int []hash = new int[26];
for(char c:p.toCharArray()){
hash[c-'a']++;
}
int left = 0, right=0;
int count = p.length();
int slen = s.length();
int plen = p.length();
while(right<slen){
//因为hash初始化默认为0,所以--hash[]操作,判断是否为p中元素,
//未在p中元素对应的数组值--操作后小于0.
if(--hash[s.charAt(right++)-'a']>=0){
count--;
}
if(count==0) res.add(left);
if(right-left == plen && hash[s.charAt(left++)-'a']++>=0){
count++;
}
}
return res;
}