题目链接放在这里了438. 找到字符串中所有字母异位词 - 力扣(LeetCode)
这道题的要求就是我们在一个字符串中找到另一个字符串的字母异位词,字母异位词就类似于abc,bca,cab这种关系,这道题的具体思路如下:
首先进行边界处理,对于空字符串和null值做处理(虽然你的代码中未显式写出,但这是滑动窗口题的常规操作)。接着,我们定义一个长度为26的数组map来存储目标字符串p中各个字符的频次,同时定义一个变量total记录目标字符串的长度,以及一个变量count用来记录当前窗口中已经匹配上的有效字符个数。
然后我们就可以逐个字符遍历字符串s了。每到一个新的字符,我们首先判断该字符在map中的频次是否大于0,如果大于0,说明这个字符是我们需要的,于是将count加1。紧接着,无论该字符是否是我们需要的,都要在map中将其对应的频次减1,以表示将当前字符纳入窗口并消耗掉一个名额。
接下来判断当前窗口是否还在初始阶段(即索引i小于total),如果是,只需判断count是否等于total,相等则说明找到了异位词,将起始下标加入结果集即可。
如果窗口已经滑动,我们需要把滑出窗口左侧的字符(即cs[i-total])对应的频次在map中加1。此时要特别注意一个小细节:在恢复频次之前,如果该字符在map中的值等于-1,说明它之前是被多消耗掉的,现在加1后刚好变为0,意味着我们"还回"了一个有效字符,此时必须将count减1。最后,再次判断count是否等于total,如果相等,说明当前窗口内的字符种类和数量与目标字符串完全一致,将当前窗口的起始下标加入结果集,遍历结束后返回即可。
这道题在掌握了滑动窗口和数组计数的思想之后做起来还是没什么困难的,但是有个小细节需要注意下,就是count的维护一定要和map的频次变化严格同步。我们在处理的时候,只有当字符从"缺少"(>0)变为"匹配"(<=0)时才增加count,只有当字符从"多余"(<0)变为"匹配"(>=0)时才减少count,具体代码实现如下:
java
class Solution {
public List<Integer> findAnagrams(String s, String p) {
List<Integer> res = new ArrayList<>();
int[] map = new int[26];
for(char c:p.toCharArray()){
map[c-'a']++;
}
char[] cs = s.toCharArray();
int total = p.length();
int count = 0;
for(int i = 0;i<cs.length;i++){
if(map[cs[i]-'a']>0){
count++;
}
map[cs[i]-'a']--;
if(i<total){
if(count==total){
res.add(i-total+1);
}
continue;
}
map[cs[i-total]-'a']++;
if(map[cs[i-total]-'a']>0){
count--;
}
if(count==total){
res.add(i-total+1);
}
}
return res;
}
}