Find All Anagrams in a String
Given a string s and a non-empty string p, find all the start indices of p’s anagrams in s.
Strings consists of lowercase English letters only and the length of both strings s and p will not be larger than 20,100.
The order of output does not matter.
Example 1:
Input:
s: "cbaebabacd" p: "abc"</br>
Output:
[0, 6]</br>
Explanation:
The substring with start index = 0 is "cba", which is an anagram of "abc".
The substring with start index = 6 is "bac", which is an anagram of "abc".
Example 2:
Input:
s: "abab" p: "ab"</br>
Output:
[0, 1, 2]</br>
Explanation:
The substring with start index = 0 is "ab", which is an anagram of "ab".
The substring with start index = 1 is "ba", which is an anagram of "ab".
The substring with start index = 2 is "ab", which is an anagram of "ab".
Code:
class Solution {
public List findAnagrams(String s, String p) {
Map< Character, Integer> map = new HashMap< Character, Integer>();
List< Integer> res = new ArrayList();
char[] pArray = p.toCharArray();
if (s == null || p == null || s.length() == 0 || p.length() == 0) return res;
for (char c : pArray) {
map.put(c, map.getOrDefault(c, 0) + 1);
}
int right = 0, left = 0, counter = map.size();
while (right < s.length()) {
char c = s.charAt(right);
if (map.containsKey(c)) {
map.put(c, map.get(c) - 1);
if (map.get(c) == 0) counter--; //右边窗口排除一个有用字符,counter--
}
right++; //还有需要查找的有用字符,移动右端窗口
while (counter == 0) { //有用字符长度为0,则移动左端窗口
char temp = s.charAt(left);
if (map.containsKey(temp)) {
map.put(temp, map.get(temp) + 1);
if (map.get(temp) > 0) counter++; //左边窗口增加一个有用字符,counter++
}
if (right - left == p.length()) res.add(left);
left++;
}
}
return res;
}
}
</code></pre>
***
* 先用HashMap对p字符串进行记录,将出现次数存入value中;
* 在遍历s字符串的过程中,使用滑动窗口;
* 移动窗口右边界,找到HashMap中的元素,将频数减一,如果频数降为零,counter减一;
* counter为零时移动左边窗口,如果元素出现在HashMap中,增加频数,如果频数大于零,则counter加一;
* 如果窗口长度等于p的长度,则输出一个满足条件的结果。