题目要求
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"
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".
思路和代码
这是一个简单的双指针问题,即左指针指向可以作为起点的子数组下标,右指针则不停向右移动,将更多的元素囊括进来,从而确保该左右指针内的元素是目标数组的一个兄弟子数组(即每个字母的个数均相等)
public List<Integer> findAnagrams(String s, String p) {
List<Integer> result = new ArrayList<Integer>();
if(p==null || s==null || p.isEmpty() || s.isEmpty()) return result;
//左指针
int startIndex = 0;
//记录每个字母出现的次数
int[] map = new int[26];
for(char c : p.toCharArray()) {
map[c-'a']++;
}
char[] sArray = s.toCharArray();
//拷贝一个临时map
int[] tmpMap = Arrays.copyOf(map, map.length);
for(int i = 0 ; i<sArray.length ; i++) {
int index = sArray[i] - 'a';
//如果该字母仍有可出现次数,则说明右指针此次移动合法
if(tmpMap[index] > 0) {
tmpMap[index]--;
//如果左右指针中数组的长度等于目标数组长度,说明该子数组合法,将左指针加入结果集中
if(i - startIndex + 1 == p.length()) {
result.add(startIndex);
tmpMap[sArray[startIndex]-'a']++;
startIndex++;//左指针右移一位
}
}else if(sArray[startIndex] == sArray[i]){//如果左右指针值相等,则左指针只向右移动一个
startIndex++;
}else {
//将左指针移动到当前右指针的位置上,因为中间部分的子数组一定无法构成目标数组
startIndex = i--;
tmpMap = Arrays.copyOf(map, map.length);
}
}
return result;
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。