Top K Frequent Elements: Count, Then Choose Your Weapon
If you interview at Amazon, Meta, Uber, expect some version of "Top K Frequent Elements". It is rated Medium, and it falls squarely into the Top-K and Heaps pattern — pattern-first preparation beats grinding random problems every time. Part 4 of 11 in the Top-K and Heaps arc.
The Problem
Return the k most frequent elements of an array, any order. The two-stage shape — build a frequency map, then select the top k entries by count — underlies a whole family (frequent words, frequent IPs in logs) and is a system design conversation seed as much as a coding question.
Input: nums = [1, 1, 1, 2, 2, 3], k = 2
Output: [1, 2]
Recognizing the Top-K and Heaps Pattern
When a problem asks for the k largest, smallest, closest, or most frequent — or for repeated access to an extreme while data changes — a heap gives O(log n) insertion and O(1) access to the extreme. The signature trick: keep a bounded heap of size k with the opposite polarity (a min-heap to track the k largest), evicting the root on overflow. Python's heapq is a min-heap; negate values for max behavior.
Top k by a derived score (frequency) is Top-K applied to a map's items. The bounded min-heap on (count, value) pairs gives O(n log k); frequencies being integers bounded by n also unlocks bucket sort at O(n) flat — a rare chance to beat the heap and name the reason (bounded key domain).
The Approach
Counter(nums) in O(n). Then maintain a size-k min-heap over (count, value): push each item, evict the root past k. Pull the survivors. heapq.nlargest(k, counter.keys(), key=counter.get) is the stdlib spelling of the same idea and is interview-legal if you can explain its internals.
Bucket variant: index lists of values by count (1..n), read buckets from the top until k collected. O(n) time, and the natural answer when the interviewer says 'can you do better than n log k?'
Python Solution
import heapq
from collections import Counter
def top_k_frequent(nums: list[int], k: int) -> list[int]:
"""K most frequent values, via a bounded min-heap over counts."""
counts = Counter(nums)
heap: list[tuple[int, int]] = []
for value, count in counts.items():
heapq.heappush(heap, (count, value))
if len(heap) > k:
heapq.heappop(heap)
return [value for _, value in heap]
Complexity
- Time: O(n log k) — n counter updates plus distinct-element pushes into a k-bounded heap
- Space: O(n) — the frequency map dominates
Interview Tips and Follow-Ups
- The problem usually guarantees a unique answer set — if ties were possible, define tie-breaking before the interviewer does.
- Top K Frequent Words adds lexicographic tie-breaks — the heap needs (−count, word) with careful ordering; a classic Amazon variant.
- At data-engineering scale, exact counts stop fitting in memory — Count-Min Sketch plus a heap is the streaming answer; one sentence of it impresses.
That wraps part 4 of the Top-K and Heaps arc. The full Technical Interview category maps all one hundred questions to the nine patterns that dominate FAANG screens — work through an arc end to end and the next unseen variant will feel familiar.
Keep reading
Find Median From a Data Stream With Two Heaps
The two-heap balance: max-heap low half, min-heap high half. Python solution and complexity analysis for the heap and top-k interview pattern.
K Closest Points to Origin Without Square Roots
Bounded max-heap on squared distance — monotone transforms are free. Python solution and complexity analysis for the heap and top-k interview pattern.
Find K Pairs With Smallest Sums: Frontier Expansion
Explore an implicit sorted matrix — seed one row, expand neighbors lazily. Python solution and complexity analysis for the heap and top-k interview pattern.
Newsletter
New posts, straight to your inbox
One email per post. No spam, no tracking pixels, unsubscribe anytime.
Comments
- No comments yet. Be the first.