--- title: 'Frequency Map' description: 'Converging/parallel index walk that prunes the O(n^2) pair space using order.' --- ## The idea A frequency map is a hash table with one job: **count things**. Key = the thing. Value = how many times you saw it. One pass to build. O(1) to ask "how many?" Most string and array problems fall to this question: "Do these two collections contain the same stuff?" Count both. Compare the counts. ## The picture ```mermaid flowchart LR S["'banana'"] --> C["Counter"] C --> B["b → 1"] C --> A["a → 3"] C --> N["n → 2"] 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:
1 1 1 2 2 3"] --> B["Count:
1→3, 2→2, 3→1"] B --> C["Buckets by count:
slot 3: [1]
slot 2: [2]
slot 1: [3]"] C --> D["Walk from top:
[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