Problem Statement

Top K Frequent Elements

You are given a list of whole numbers called nums and a number k. Your job is to find the k numbers that show up the most times in the list. You can return those numbers in any order. For example, if a number appears 5 times and another appears 3 times, the one that appears 5 times is "more frequent."

mediumHeapHeap / Priority QueueTime: O(n log k) · Space: O(n)

Signals to notice

find k most frequent elementsfrequency counting then selectiondon't need full sort

Brute force first

Count frequencies, sort by frequency, take top k. Sorting is overkill when you only need the top k. That direct path helps you understand the question, but it tends to treat every possibility as brand new instead of learning from earlier steps.

The key insight

Count frequencies with a hash map, then use a min-heap of size k to track the top k elements. — the heap never grows beyond k elements. Instead of recomputing the world every time, you preserve just enough context to let the next decision become obvious.

Trace it on nums=[1,1,1,2,2,3], k=2

count = Counter(nums) -> {1:3, 2:2, 3:1}; heap=[]
push (3,1): heap=[(3,1)]; size 1 <= k=2, keep
push (2,2): heap=[(2,2),(3,1)]; size 2 <= k=2, keep
push (1,3): heap=[(1,3),(3,1),(2,2)]; size 3 > k=2 -> pop smallest (1,3)
after pop: heap=[(2,2),(3,1)]; min freq 2 is the threshold
all items processed; heap holds the 2 most frequent
return [num for freq,num in heap] -> [2,1] (any order accepted)

What must stay true

The min-heap's smallest element is always the threshold — if a new frequency is larger, swap it in. After processing all elements, the heap contains exactly the k most frequent. As long as that statement keeps holding, you can trust the steps built on top of it.

Shape of the loop

count = frequency_map(nums)
heap = []                       # min-heap keyed by frequency
for (num, freq) in count:
    push(heap, (freq, num))
    if size(heap) > k: pop(heap) # evict smallest freq
return [num for (freq, num) in heap]

Pseudocode only — the full worked solution lives in the Solution tab.

Easy way to go wrong

Using a max-heap — that finds the maximum, not the top k. A min-heap of size k naturally evicts the smallest, keeping only the largest k frequencies. Most mistakes here are not about syntax; they come from losing track of what your state, pointer, or structure is supposed to mean.

Heap / Priority Queue Pattern