题目

思路

利用定长滑动窗口,增量维护频次数组。

Java

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
class Solution {
    public List<Integer> findAnagrams(String s, String p) {
        List<Integer> res = new ArrayList<>();

        int n = s.length(), m = p.length();
        if (n < m) return res;

        int[] cnt = new int[26];
        for (int i = 0; i < m; i ++) {
            cnt[p.charAt(i) - 'a'] ++;
        }

        int diff = m;
        int left = 0;

        for (int right = 0; right < n; right ++) {
            // 进窗口
            int in = s.charAt(right) - 'a';
            if (cnt[in] > 0) {
                diff --;
            }
            cnt[in]--;

            // 出窗口
            if (right - left + 1 > m) {
                int out = s.charAt(left) - 'a';
                if (cnt[out] >= 0) {
                    diff ++;
                }
                cnt[out] ++;
                left ++;
            }

            // 结算答案
            if (right - left + 1 == m && diff == 0) {
                res.add(left);
            }
        }
        return res;
    }
}

Python

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class Solution:
    def findAnagrams(self, s: str, p: str) -> List[int]:
        n, m = len(s), len(p)
        if n < m:
            return []
        
        cnt = [0] * 26
        for ch in p:
            cnt[ord(ch) - 97] += 1
        
        diff = m
        left = 0
        ans = []

        for right, ch in enumerate(s):
            idx_in = ord(ch) - 97
            if cnt[idx_in] > 0:
                diff -= 1
            cnt[idx_in] -= 1

            if right - left + 1 > m:
                idx_out = ord(s[left]) - 97
                if cnt[idx_out] >= 0:
                    diff += 1
                cnt[idx_out] += 1
                left += 1

            if right - left + 1 == m and diff == 0:
                ans.append(left)

        return ans

JS

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
/**
 * @param {string} s
 * @param {string} p
 * @return {number[]}
 */
var findAnagrams = function(s, p) {
    const n = s.length, m = p.length;
    if (n < m) return [];

    const cnt = new Array(26).fill(0);
    for (let i = 0; i < m; i ++) {
        cnt[p.charCodeAt(i) - 97] ++;
    }

    let diff = m;
    let left = 0;
    const ans = [];

    for (let right = 0; right < n; right ++) {
        const inIdx = s.charCodeAt(right) - 97;
        if (cnt[inIdx] > 0) diff--;
        cnt[inIdx]--;

        if (right - left + 1 > m) {
            const outIdx = s.charCodeAt(left) - 97;

            if (cnt[outIdx] >= 0) diff ++;
            cnt[outIdx] ++;
            left ++;
        }

        if (right - left + 1 === m && diff === 0) {
            ans.push(left);
        }
    }
    return ans;
};

Go

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
func findAnagrams(s string, p string) []int {
    n, m := len(s), len(p)
    if n < m {
        return []int{}
    }

    cnt := make([]int, 26)
    for i := 0; i < m ;i ++ {
        cnt[p[i] - 'a'] ++
    }
    
    diff := m
    left := 0
    ans := make([]int, 0)
    for right := 0; right < n; right ++ {
        in := s[right] - 'a'
        if cnt[in] > 0 {
            diff--
        }
        cnt[in]--

        if right - left + 1 > m {
            out := s[left] - 'a'
            if cnt[out] >= 0 {
                diff++
            }
            cnt[out]++
            left++
        }

        if right - left + 1 == m  && diff == 0 {
            ans = append(ans, left)
        }
    }
    return ans
}