|  | 
| 5 | 5 | - [Approach 1: Brute-force Checking](#approach-1-brute-force-checking) | 
| 6 | 6 | - [Approach 2: Sorting and HashMap](#approach-2-sorting-and-hashmap) | 
| 7 | 7 | - [Approach 3: Efficient Sliding Window with HashMap](#approach-3-efficient-sliding-window-with-hashmap) | 
| 8 |  | - | 
|  | 8 | +- [Approach 4: Simplified Sliding Window with Counter](#approach-4-sliding-window-with-counter) | 
| 9 | 9 | --- | 
| 10 | 10 | 
 | 
| 11 | 11 | ## Approach 1: Brute-force Checking | 
| @@ -129,3 +129,63 @@ findAnagrams("cbaebabacd", "abc") | 
| 129 | 129 | ### Space Complexity | 
| 130 | 130 | - O(1), as the space used by the Counter is constant relative to the fixed character set (assuming only lowercase letters). | 
| 131 | 131 | 
 | 
|  | 132 | +## Approach 4: Sliding Window with Counter | 
|  | 133 | +### Intuition | 
|  | 134 | + | 
|  | 135 | +When looking for anagrams in a text, we need to compare character frequencies. Since we're looking for all possible positions, using a sliding window approach that maintains and updates character counts feels natural - this way we don't have to recount characters for each possible position. | 
|  | 136 | + | 
|  | 137 | +### Approach | 
|  | 138 | + | 
|  | 139 | +1.  First validate the inputs - if either string is empty or the text is shorter than pattern, return empty list | 
|  | 140 | +2.  Create a frequency counter for the pattern we're looking for | 
|  | 141 | +3.  Create initial window of pattern length at start of text and count its characters | 
|  | 142 | +4.  Compare first window with pattern - if they match, we found our first anagram | 
|  | 143 | +5.  For rest of text, slide window one character at a time: | 
|  | 144 | +    -   Add new character on right to window count | 
|  | 145 | +    -   Remove leftmost character from window count | 
|  | 146 | +    -   If character count becomes zero, remove it completely | 
|  | 147 | +    -   Compare current window with pattern | 
|  | 148 | +    -   If frequencies match, add starting position to results | 
|  | 149 | +6.  Return all positions where anagrams were found | 
|  | 150 | + | 
|  | 151 | +### Code | 
|  | 152 | +```python | 
|  | 153 | +from collections import Counter | 
|  | 154 | + | 
|  | 155 | +def find_anagrams(text: str, pattern: str) -> list: | 
|  | 156 | +    """Find starting indices of pattern's anagrams in text.""" | 
|  | 157 | +    if not text or not pattern or len(text) < len(pattern): | 
|  | 158 | +        return [] | 
|  | 159 | +     | 
|  | 160 | +    result = [] | 
|  | 161 | +    pattern_count = Counter(pattern) | 
|  | 162 | +    window_count = Counter(text[:len(pattern)]) | 
|  | 163 | +     | 
|  | 164 | +    # Check first window | 
|  | 165 | +    if window_count == pattern_count: | 
|  | 166 | +        result.append(0) | 
|  | 167 | +         | 
|  | 168 | +    # Slide window: remove left char, add right char, check if anagram | 
|  | 169 | +    for i in range(len(pattern), len(text)): | 
|  | 170 | +        window_count[text[i]] += 1 | 
|  | 171 | +        window_count[text[i - len(pattern)]] -= 1 | 
|  | 172 | +         | 
|  | 173 | +        # Clean up zero counts | 
|  | 174 | +        if window_count[text[i - len(pattern)]] == 0: | 
|  | 175 | +            del window_count[text[i - len(pattern)]] | 
|  | 176 | +             | 
|  | 177 | +        if window_count == pattern_count: | 
|  | 178 | +            result.append(i - len(pattern) + 1) | 
|  | 179 | +             | 
|  | 180 | +    return result | 
|  | 181 | +``` | 
|  | 182 | + | 
|  | 183 | +### Complexity | 
|  | 184 | + | 
|  | 185 | +-   Time complexity: $$O(n)$$ where n is length of input text | 
|  | 186 | +    -   We scan text once with constant time operations at each step | 
|  | 187 | +    -   Counter comparisons are O(k) where k is alphabet size (constant) | 
|  | 188 | +-   Space complexity: $$O(k)$$ where k is size of alphabet | 
|  | 189 | +    -   We store two frequency counters | 
|  | 190 | +    -   Each counter has at most k entries (one per unique character) | 
|  | 191 | +    -   k is limited by alphabet size, so effectively O(1) | 
0 commit comments