Leetcode: 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"

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".

Time Complexity will be O(n) because the "start" and "end" points will only move from left to right once.

Sliding Window: Use a count to denote the difference between current sliding window and p, if count == 0, means the current sliding window is the same with p, add start to the result

refer to https://discuss.leetcode.com/topic/64434/shortest-concise-java-o-n-sliding-window-solution/2

 1 public class Solution {
 2     public List<Integer> findAnagrams(String s, String p) {
 3         List<Integer> list = new ArrayList<>();
 4     if (s == null || s.length() == 0 || p == null || p.length() == 0) return list;
 5     
 6     int[] hash = new int[256]; //character hash
 7     
 8     //record each character in p to hash
 9     for (char c : p.toCharArray()) {
10         hash[c]++;
11     }
12     //two points, initialize count to p's length
13     int left = 0, right = 0, count = p.length();
14     
15     while (right < s.length()) {
16         //move right everytime, if the character exists in p's hash, decrease the count
17         //current hash value >= 1 means the character is existing in p
18         if (hash[s.charAt(right)] >= 1) { //char at right is in p, so is needed to make an anagram of p, so if we shift our window to
19             count--;             // include right, the difference between our window and p will decrease by 1, so count-1
20         }
21         hash[s.charAt(right)]--;      //Other case if hash[s.charAt(right)] right now == 0, which means we do not need it, we do not decrease count
22         right++;                // hash[s.charAt(right)] will be -1, if window contains some char that p do not need, count will never reach 0
23                              // whereas some hash[somewhere] will be negative, some hash[somewhereelse] will be positive
24         //when the count is down to 0, means we found the right anagram
25         //then add window's left to result list
26         if (count == 0) {          // this is only when p's chars and window's chars are all the same
27             list.add(left);
28         }
29         //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
30         //++ to reset the hash because we kicked out the left
31         //only increase the count if the character is in p
32         //the count >= 0 indicate it was original in the hash, cuz it won't go below 0
33         if (right - left == p.length() ) {
34            
35             if (hash[s.charAt(left)] >= 0) {
36                 count++;
37             }
38             hash[s.charAt(left)]++;
39             left++;
40         
41         }
42 
43         
44     }
45         return list;
46     }
47 }
原文地址:https://www.cnblogs.com/EdwardLiu/p/6128474.html