Skip to content

Commit c1968e4

Browse files
authored
Update find-all-anagrams-in-a-string.md
1 parent e07e701 commit c1968e4

File tree

1 file changed

+61
-1
lines changed

1 file changed

+61
-1
lines changed

python/find-all-anagrams-in-a-string.md

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
- [Approach 1: Brute-force Checking](#approach-1-brute-force-checking)
66
- [Approach 2: Sorting and HashMap](#approach-2-sorting-and-hashmap)
77
- [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)
99
---
1010

1111
## Approach 1: Brute-force Checking
@@ -129,3 +129,63 @@ findAnagrams("cbaebabacd", "abc")
129129
### Space Complexity
130130
- O(1), as the space used by the Counter is constant relative to the fixed character set (assuming only lowercase letters).
131131

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

Comments
 (0)