题目
Given two strings
sandp, return an array of all the start indices ofp's anagrams ins. You may return the answer in any order. An Anagram is a word or phrase formed by rearranging the letters of a different word or phrase, typically using all the original letters exactly once.
给两个string s和p, 返回s中包含p所有字符的子串起点下标
Example 1:
Input: s = "cbaebabacd", p = "abc"
Output: [0,6]
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"
Output: [0,1,2]
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".
Constraints:
1 <= s.length, p.length <= 3 * 10^4sandpconsist of lowercase English letters.
思路
- 典型的滑动窗口,直接开套
- 不考虑顺序,有重复值,p的字符用pMap维护
- 循环s的所有字符,放入另一个sMap,使用滑动窗口保证sMap的size始终和pMap一样,
- 这种情况下判断两个Map内元素及数量是否一致
代码
public List<Integer> findAnagrams(String s, String p) {
//快速判断特殊情况
if (p.length() > s.length()) {
return Collections.emptyList();
}
List<Integer> result = new ArrayList<>();
//定义两个map分别存储s和p的字符
Map<Character, Integer> pCharMap = new HashMap<>();
Map<Character, Integer> sCharMap = new HashMap<>();
//初始化p的Map
for(char c : p.toCharArray()) {
pCharMap.merge(c, 1, Integer::sum);
}
for(int i = 0; i < s.length(); i++) {
sCharMap.merge(s.charAt(i), 1, Integer::sum);
//当滑动窗口=p的大小时开始滑动
if (i >= p.length()) {
//剔除最左侧的字符
char left = s.charAt(i - p.length());
if (sCharMap.get(left) == 1) {
sCharMap.remove(left);
} else {
sCharMap.put(left, sCharMap.get(left) - 1);
}
}
//如果此时两个Map元素一样,存入起点下标
if (pCharMap.equals(sCharMap)) {
result.add(i - p.length() + 1);
}
}
return result;
}