题目
给定一个字符串 s 和一个非空字符串 p,找到 s 中所有是 p 的字母异位词的子串,返回这些子串的起始索引。
字符串只包含小写英文字母,并且字符串 s 和 p 的长度都不超过 20100。
说明:
字母异位词指字母相同,但排列不同的字符串。
不考虑答案输出的顺序。
示例 1:
输入:
s: “cbaebabacd” p: “abc”
输出:
[0, 6]
解释:
起始索引等于 0 的子串是 “cba”, 它是 “abc” 的字母异位词。
起始索引等于 6 的子串是 “bac”, 它是 “abc” 的字母异位词。
示例 2:
输入:
s: “abab” p: “ab”
输出:
[0, 1, 2]
解释:
起始索引等于 0 的子串是 “ab”, 它是 “ab” 的字母异位词。
起始索引等于 1 的子串是 “ba”, 它是 “ab” 的字母异位词。
起始索引等于 2 的子串是 “ab”, 它是 “ab” 的字母异位词。
解题
- 这一题LeetCode标注为简单, 但其实解答起来还挺复杂的, 最主要的就是在于对异位词的判断
代码如下 :
class Solution {
public List<Integer> findAnagrams(String s, String p) {
// 用于标识这个
int count = p.length();
List<Integer> result = new ArrayList<>();
if(s.length() < count){
return result;
}
HashMap<Character, Integer> map = new HashMap<>();
char[] chars = p.toCharArray();
for (char aChar : chars) {
map.put(aChar, map.containsKey(aChar) ? map.get(aChar) + 1 : 1);
}
char[] sChars = s.toCharArray();
// 用s串的[left, right]表示p的异位词, 当count为0时表示是异位词
int left = 0, right = -1;
// if (map.containsKey(sChars[0])){
// count--;
// map.put(sChars[0], map.get(sChars[0]) - 1);
// }
while (right < s.length() && left < s.length() - p.length() + 1){
if (right - left == p.length() - 1){
if (count == 0){
result.add(left);
}
count = moveLeft(sChars, map, left, count);
left++;
}
count = moveRight(sChars, map, right, count);
right++;
}
return result;
}
// left右移一位
private int moveLeft(char[] sChars, HashMap<Character, Integer> map, int left, int count){
if (map.containsKey(sChars[left])){
if (map.get(sChars[left]) >= 0){
count++;
}
map.put(sChars[left], map.get(sChars[left]) + 1);
}
return count;
}
// right右移一位, 返回count的值
private int moveRight(char[] sChars, HashMap<Character, Integer> map, int right, int count){
if (right + 1 > sChars.length - 1) {
return count;
}
if (map.containsKey(sChars[right + 1])){
if (map.get(sChars[right + 1]) > 0){
count--;
}
map.put(sChars[right + 1], map.get(sChars[right + 1]) - 1);
}
return count;
}
public static void main(String[] args) {
List<Integer> anagrams = new Solution().findAnagrams("abab", "ab");
System.out.println(anagrams);
}
}
LeetCode上提交的用时最短的解答如下:
class Solution {
public List<Integer> findAnagrams(String s, String p) {
List<Integer> list=new ArrayList<Integer>();
int[] sump=new int[123];
int[] sums=new int[123];
char[] chs=s.toCharArray();
char[] chp=p.toCharArray();
int k=chp.length,end=chp.length;
if(chs.length<end) return list;
for(int i=0;i<end;i++){
sump[chp[i]]++;
sums[chs[i]]++;
}
while(true){
boolean flag=true;
for(int j=97;j<123;j++){
if(sums[j]!=sump[j]) {
flag=false;
break;
}
}
if(flag)list.add(k-end);
if(k==chs.length)break;
sums[chs[k-end]]--;
sums[chs[k]]++;
k++;
}
return list;
}
}