438. Find All Anagrams in a String

39 阅读1分钟

image.png

solution: Sliding window + counter, O(N), O(K)

simplest approach: sliding window + two counter hashmaps letter -> its count. The first hashmap is a reference counter pCount for string p, and the second one is a counter sCount for a string in the sliding window.

The idea is to move the sliding window along the string s, recompute the second hashmap sCount in a constant time, and compare it with the first hashmap pCount. If sCount == pCount, then the string in the sliding window is a permutation of string p, and one could add its start position in the output list.

class Solution {
    public List<Integer> findAnagrams(String s, String p) {
        // count char frequency in p
        Map<Character, Integer> pmap = new HashMap<>();
        for (int i = 0; i < p.length(); i++) {
            char c = p.charAt(i);
            pmap.put(c, pmap.getOrDefault(c, 0) + 1);
        }
        
        int i = 0, j = 0;
        List<Integer> res = new ArrayList<>();
        Map<Character, Integer> smap = new HashMap<>();
        while (i < s.length() && j < s.length()) {
            // always to update smap for every character in s (rather than only those in p)
            char r = s.charAt(j);
            smap.put(r, smap.getOrDefault(r, 0) + 1);
            
            // contract window size via i++ when window exceed p's size
            if (j - i >= p.length()) {
                char l = s.charAt(i);
                smap.put(l, smap.get(l) - 1);
                if (smap.get(l) == 0) {
                    smap.remove(l);
                }
                i++;
            }

            if (smap.equals(pmap)) {
                res.add(i);
            }

            j++; // expand window size
        }

        return res;

    }
}
class Solution { public List<Integer> findAnagrams(String s, String p) { int[] pFreq = new int[26]; for (int i = 0; i < p.length(); i++) { char c = p.charAt(i); pFreq[c - 'a']++; } int i = 0, j = 0; List<Integer> res = new ArrayList<>(); int[] sFreq = new int[26]; while (i < s.length() && j < s.length()) { // always to update smap for every character in s (rather than only those in p) char r = s.charAt(j); sFreq[r - 'a']++; if (j - i >= p.length()) { char l = s.charAt(i); sFreq[l - 'a']--; i++; } if (Arrays.equals(sFreq, pFreq)) { // Arrays.equals, not a.equals(b) res.add(i); } j++; } return res; } }