错误解法(这种解法对于很大的输入会造成超时,循环是O(N),判断的函数又是O(N),总复杂度是O(N^2)了):
public class Solution {
private boolean isSame(char[] a, char[] b){
for(int i = 0; i < a.length; i++){
if(a[i] != b[i])
return false;
}
return true;
}
public List<Integer> findAnagrams(String s, String p) {
List<Integer> res = new ArrayList<>();
char[] pa = p.toCharArray();
Arrays.sort(pa);
for(int i = 0; i < s.length() - p.length() + 1; i++){
char[] sa = s.substring(i, i + p.length()).toCharArray();
Arrays.sort(sa);
if(isSame(sa, pa)){
res.add(i);
}
}
return res;
}
}
正解:
public class Solution {
//Same idea from a fantastic sliding window template,与比较子串有关的都可以采用这种算法,window就是子串
//Time Complexity will be O(n) because the "start" and "end" points will only move from left to right once.
public List<Integer> findAnagrams(String s, String p) {
List<Integer> list = new ArrayList<>();
if (s == null || s.length() == 0 || p == null || p.length() == 0)
return list;
int[] hash = new int[256]; //character hash,256保险起见,字符个数不可能多于256个
//record each character in p to hash
for (char c : p.toCharArray()) {
hash[c]++;
}
//two points, initialize count to p's length
int left = 0, right = 0, count = p.length();
while (right < s.length()) {
//move right everytime, if the character exists in p's hash, decrease the count
//current hash value >= 1 means the character is existing in p
if (hash[s.charAt(right)] >= 1) {
count--;
}
hash[s.charAt(right)]--;
right++;
//when the count is down to 0, means we found the right anagram
//then add window's left to result list
if (count == 0) {
list.add(left);
}
//if we find the window's size equals to p, then we have to move left (narrow the window) to find the new match window
//++ to reset the hash because we kicked out the left
//only increase the count if the character is in p
//the count >= 0 indicate it was original in the hash, cuz it won't go below 0
if (right - left == p.length() ) {//需要找一个新的window了,需要移动left,而且要将count与hash复原
if (hash[s.charAt(left)] >= 0) {//因为left只移动一个位置,而中间right移动那些不用变(之后也会同样地),所以复原一个count++
count++;
}
hash[s.charAt(left)]++;//因为left只移动一个位置,而中间right移动那些不用变(之后也会同样地),所以复原一个hash[s.charAt(left)]
left++;
}
}
return list;
}
}