[LeetCode] 438. 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 consist 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".

找到字符串中所有字母易位词。给定一个字符串 s 和一个非空字符串 p,找到 s 中所有是 p 的字母异位词的子串,返回这些子串的起始索引。思路是滑动窗口(sliding window)。这个题也可以用之前的模板做,参见76,159,340。先遍历p,得到p中每个字母和他们对应的出现次数。再去遍历s,用start和end指针,end在前,当某个字母的出现次数被减少到0的时候,counter才能--。当counter == 0的时候,判断end - begin是否等于p的长度,若是,才能将此时begin的坐标加入结果集。

时间O(n)

空间O(1)

Java实现

 1 class Solution {
 2     public List<Integer> findAnagrams(String s, String p) {
 3         List<Integer> res = new ArrayList<>();
 4         // corner case
 5         if (s.length() < p.length()) {
 6             return res;
 7         }
 8 
 9         // normal case
10         int[] map = new int[128];
11         for (char c : p.toCharArray()) {
12             map[c]++;
13         }
14         int counter = p.length();
15         int start = 0;
16         int end = 0;
17         while (end < s.length()) {
18             char c1 = s.charAt(end);
19             if (map[c1] > 0) {
20                 counter--;
21             }
22             map[c1]--;
23             end++;
24             while (counter == 0) {
25                 char c2 = s.charAt(start);
26                 map[c2]++;
27                 if (map[c2] > 0) {
28                     counter++;
29                 }
30                 if (end - start == p.length()) {
31                     res.add(start);
32                 }
33                 start++;
34             }
35         }
36         return res;
37     }
38 }

JavaScript实现

 1 /**
 2  * @param {string} s
 3  * @param {string} p
 4  * @return {number[]}
 5  */
 6 var findAnagrams = function(s, p) {
 7     let res = [];
 8     if (p.length > s.length) {
 9         return res;
10     }
11 
12     let map = new Map();
13     for (let c of p) {
14         map.set(c, (map.get(c) | 0) + 1);
15     }
16 
17     let begin = 0,
18         end = 0,
19         counter = map.size;
20     while (end < s.length) {
21         let c = s.charAt(end);
22         if (map.has(c)) {
23             map.set(c, map.get(c) - 1);
24             if (map.get(c) === 0) {
25                 counter--;
26             }
27         }
28         end++;
29         while (counter === 0) {
30             let d = s.charAt(begin);
31             if (map.has(d)) {
32                 map.set(d, map.get(d) + 1);
33                 if (map.get(d) > 0) {
34                     counter++;
35                 }
36             }
37             if (end - begin == p.length) {
38                 res.push(begin);
39             }
40             begin++;
41         }
42     }
43     return res;
44 };

sliding window相关题目

LeetCode 题目总结

原文地址:https://www.cnblogs.com/cnoodle/p/12626540.html