|
1 | 1 | /**
|
2 | | - * @param {string} s |
3 | | - * @param {string} p |
4 | | - * @return {number[]} |
| 2 | + * @param {string} stream Input string. |
| 3 | + * @param {string} word Word to compare substring to. |
| 4 | + * @return {number[]} Array with indexes of all substrings that are anagrams of word. |
| 5 | + * @summary Find All Anagrams in a String {@link https://leetcode.com/problems/find-all-anagrams-in-a-string/} |
| 6 | + * @description Given two input strings return indexes of substrings that are anagrams of second input. |
| 7 | + * Space O(A+B) - A length of string 'word', B length of string 'stream'. |
| 8 | + * Time O(1) - Two new arrays, each of 26 elements. |
5 | 9 | */
|
| 10 | +const findAnagrams = (stream, word) => { |
| 11 | + const counts = Array(26); |
| 12 | + const currentCount = Array(26); |
| 13 | + const offset = 'a'.charCodeAt(); |
| 14 | + const answer = []; |
| 15 | + const sLength = stream.length; |
| 16 | + const wLength = word.length; |
6 | 17 |
|
7 | | -constisAnagram=(word,candidate)=> { |
8 | | - if(word.length!==candidate.length)returnfalse; |
| 18 | +for(leti=0;i<wLength;i++) { |
| 19 | + constindex=word[i].charCodeAt()-offset; |
9 | 20 |
|
10 | | - const charMap = {}; |
11 | | - for (let index = 0; index < word.length; index++) { |
12 | | - if (word.indexOf(candidate[index]) < 0) { |
13 | | - return false; |
14 | | - } |
15 | | - charMap[word[index]] = charMap[word[index]] ? charMap[word[index]] + 1 : 1; |
16 | | - charMap[candidate[index]] = charMap[candidate[index]] ? charMap[candidate[index]] - 1 : -1; |
| 21 | + counts[index] = counts[index] ? counts[index] + 1 : 1; |
17 | 22 | }
|
18 | 23 |
|
19 | | - return Object.keys(charMap).every(char => charMap[char] === 0); |
20 | | -}; |
21 | | - |
22 | | -const findAnagrams = (s, p) => { |
23 | | - const anagrams = {}; |
24 | | - anagrams[p] = true; |
| 24 | + for (let i = 0; i < sLength; i++) { |
| 25 | + const index = stream[i].charCodeAt() - offset; |
25 | 26 |
|
26 | | - const answer = []; |
27 | | - |
28 | | - const length = s.length - p.length + 1; |
29 | | - for (let index = 0; index < length; index++) { |
30 | | - const candidate = s.slice(index, index + p.length); |
| 27 | + currentCount[index] = currentCount[index] ? currentCount[index] + 1 : 1; |
31 | 28 |
|
32 | | - if (anagrams[candidate] === undefined) anagrams[candidate] = isAnagram(p, candidate); |
| 29 | + if (i >= wLength) { |
| 30 | + const index = stream[i - wLength].charCodeAt() - offset; |
| 31 | + currentCount[index] = currentCount[index] ? currentCount[index] - 1 : undefined; |
| 32 | + } |
33 | 33 |
|
34 | | - if (anagrams[candidate]) answer.push(index); |
| 34 | + if (counts.every((count, index) => count === currentCount[index])) { |
| 35 | + answer.push(i - wLength + 1); |
| 36 | + } |
35 | 37 | }
|
36 | 38 |
|
37 | 39 | return answer;
|
|
0 commit comments