一、题目内容
二、题目分析
第一步:明确本题可以使用滑动窗口解决。
第二步:定义一个list储存数据,初始为空。
第三步:判断s和p的长度,当p长度大于s时,直接返回空的list。
第四步:因为只可以是小写字母,所以定义两个长度为26的数组储存各字母出现的次数。
第五步:假设s的长度为slen,p的长度为plen。那么判断s的前plen个和p字母出现的次数是否相等,若相等就把0加入list,否则进行下一步。
第六步:另i从plen开始到slen,每次都将s数组中第(i-plen)个数删掉,加入第i个数,然后判断和p是否相等,相等就加入(i-plen+1),否则继续。
解释第四步:为什么要定义两个长度为26的数组?
首先,我们找的异位词的定义时两个字符串的长度相等,出现的字母次数也相等,唯一不同的就是字母的排列顺序。我们用一个长度为26的数组记录从a到z字母出现的次数很方便,出现任何一个字母都只需要让数组的对应位置加一即可。
解释第六步:为什么要取出s数组的第一个,加上最后一个。
首先,对于上面某个例子,s=cbaebcbacd,p=abc而言。当s的前三个和p相等时,我们将0放入了list,因为0是异位词的第一个。然后我们自然要从第四个开始继续寻找,那么既然前三个已经相等了,就应该看看第2,3,4个字母和p是不是异位词,为了保证长度和p的长度相等,所以要将第一个取出,并且放入第四个。以此类推即可。
代码:
public List<Integer> findAnagrams(String s, String p) {
int n=s.length(),m=p.length();
int []srnt=new int [26];
int []prnt=new int [26];
List<Integer> list=new ArrayList<>();
if(n<m)
return list;
for(int i=0;i<m;i++){
srnt[s.charAt(i)-'a']++;
prnt[p.charAt(i)-'a']++;
}
if(Arrays.equals(srnt,prnt))
list.add(0);
for(int i=m;i<n;i++){
srnt[s.charAt(i-m)-'a']--;
srnt[s.charAt(i)-'a']++;
if(Arrays.equals(srnt,prnt))
list.add(i-m+1);
}
return list;
}