2026-08-14 18:37:13 -04:00
|
|
|
---
|
2026-08-20 13:53:34 -04:00
|
|
|
title: 'Frequency Map'
|
2026-08-14 18:37:13 -04:00
|
|
|
description: 'Converging/parallel index walk that prunes the O(n^2) pair space using order.'
|
|
|
|
|
---
|
|
|
|
|
|
2026-08-20 16:04:24 -04:00
|
|
|
## The idea
|
2026-08-17 14:19:02 -04:00
|
|
|
|
2026-08-20 16:04:24 -04:00
|
|
|
A frequency map is a hash table with one job: **count things**.
|
2026-08-17 14:19:02 -04:00
|
|
|
|
2026-08-20 16:04:24 -04:00
|
|
|
Key = the thing. Value = how many times you saw it.
|
|
|
|
|
One pass to build. O(1) to ask "how many?"
|
2026-08-17 14:19:02 -04:00
|
|
|
|
2026-08-20 16:04:24 -04:00
|
|
|
Most string and array problems fall to this question:
|
|
|
|
|
"Do these two collections contain the same stuff?"
|
|
|
|
|
Count both. Compare the counts.
|
2026-08-17 14:19:02 -04:00
|
|
|
|
2026-08-20 16:04:24 -04:00
|
|
|
## The picture
|
2026-08-17 14:19:02 -04:00
|
|
|
|
2026-08-20 16:04:24 -04:00
|
|
|
```mermaid
|
|
|
|
|
flowchart LR
|
|
|
|
|
S["'banana'"] --> C["Counter"]
|
|
|
|
|
C --> B["b → 1"]
|
|
|
|
|
C --> A["a → 3"]
|
|
|
|
|
C --> N["n → 2"]
|
2026-08-19 13:05:47 -04:00
|
|
|
|
2026-08-20 16:04:24 -04:00
|
|
|
style C fill:#1565c0,color:#fff
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## The Python tool
|
|
|
|
|
|
|
|
|
|
`Counter` builds the map in one line. `defaultdict(int)` when you need to count by hand.
|
|
|
|
|
|
|
|
|
|
```python
|
|
|
|
|
from collections import Counter, defaultdict
|
|
|
|
|
|
|
|
|
|
count = Counter("banana") # {'a': 3, 'n': 2, 'b': 1}
|
|
|
|
|
count.most_common(2) # [('a', 3), ('n', 2)]
|
|
|
|
|
|
|
|
|
|
freq = defaultdict(int)
|
|
|
|
|
for c in "banana":
|
|
|
|
|
freq[c] += 1 # no KeyError, starts at 0
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## Ransom Note (LC 383) — do I have enough letters?
|
|
|
|
|
|
|
|
|
|
Count the magazine. Spend letters as the note needs them.
|
|
|
|
|
Counter subtraction does this in two lines.
|
|
|
|
|
|
|
|
|
|
```python
|
|
|
|
|
from collections import Counter
|
|
|
|
|
|
|
|
|
|
def can_construct(ransom_note: str, magazine: str) -> bool:
|
|
|
|
|
need = Counter(ransom_note)
|
|
|
|
|
have = Counter(magazine)
|
|
|
|
|
return all(have[c] >= n for c, n in need.items())
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## Top K Frequent (LC 347) — count, then rank
|
|
|
|
|
|
|
|
|
|
Two steps: count everything, then pick the k biggest counts.
|
|
|
|
|
|
|
|
|
|
```mermaid
|
|
|
|
|
flowchart LR
|
|
|
|
|
A["nums:<br/>1 1 1 2 2 3"] --> B["Count:<br/>1→3, 2→2, 3→1"]
|
|
|
|
|
B --> C["Buckets by count:<br/>slot 3: [1]<br/>slot 2: [2]<br/>slot 1: [3]"]
|
|
|
|
|
C --> D["Walk from top:<br/>[1, 2] ✓"]
|
|
|
|
|
|
|
|
|
|
style D fill:#2e7d32,color:#fff
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Bucket sort trick: a number can appear at most n times.
|
|
|
|
|
So make n+1 buckets. Put each number in the bucket of its count.
|
|
|
|
|
Walk buckets from the top. O(n) — no sort, no heap.
|
|
|
|
|
|
|
|
|
|
```python
|
|
|
|
|
from collections import Counter
|
|
|
|
|
|
|
|
|
|
def top_k_frequent(nums: list[int], k: int) -> list[int]:
|
|
|
|
|
count = Counter(nums)
|
|
|
|
|
buckets = [[] for _ in range(len(nums) + 1)]
|
|
|
|
|
for num, freq in count.items():
|
|
|
|
|
buckets[freq].append(num)
|
|
|
|
|
|
|
|
|
|
result = []
|
|
|
|
|
for freq in range(len(buckets) - 1, 0, -1):
|
|
|
|
|
for num in buckets[freq]:
|
|
|
|
|
result.append(num)
|
|
|
|
|
if len(result) == k:
|
|
|
|
|
return result
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## Say the trade-off out loud
|
|
|
|
|
|
|
|
|
|
Three ways to rank counts. Name them in the interview:
|
|
|
|
|
|
|
|
|
|
| Method | Time | When |
|
|
|
|
|
|---|---|---|
|
|
|
|
|
| Sort the counts | O(n log n) | Fine, simple |
|
|
|
|
|
| Heap of size k | O(n log k) | k small, streaming |
|
|
|
|
|
| Bucket sort | O(n) | Best — counts are bounded by n |
|
|
|
|
|
|
|
|
|
|
## Complexity
|
|
|
|
|
|
|
|
|
|
| | Time | Space |
|
|
|
|
|
|---|---|---|
|
|
|
|
|
| Build the map | O(n) | O(u) — unique items |
|
|
|
|
|
| Lookup | O(1) | — |
|
|
|
|
|
|
|
|
|
|
## Close-out ritual
|
|
|
|
|
|
|
|
|
|
Before you submit, say out loud:
|
|
|
|
|
1. Time and space complexity.
|
|
|
|
|
2. One edge case trace: empty string, k = number of unique items, or one element repeated n times.
|
|
|
|
|
|
|
|
|
|
## Plan problems
|
|
|
|
|
|
|
|
|
|
**A-set:** LC 217 · 242 · 1 · 49 · 347
|
|
|
|
|
**B-set:** LC 383 · 205 · 128 · 290
|