The Problem

Given an integer array nums and an integer k, return the k most frequent elements. You may return the answer in any order.

It is guaranteed that the answer is unique.

Interactive Visualization

Phase 1: Count Frequencies
Phase 2: Heap Selection
Result
Speed:
Input Array
Frequency Map
Empty — frequencies will be counted as the algorithm runs
Min-Heap (size ≤ k = 2)
Empty — heap entries will appear during Phase 2
Result
Will appear after heap selection completes
Step Log
Press Step or Play to begin.
Code
import java.util.PriorityQueuefun topKFrequent(nums: IntArray, k: Int): List<Int> {    val count = hashMapOf<Int, Int>()    for (n in nums) count[n] = (count[n] ?: 0) + 1    val heap = PriorityQueue<Pair<Int,Int>>(compareBy { it.first })    for ((num, freq) in count) {        heap.add(Pair(freq, num))        if (heap.size > k)            heap.poll()    }    return heap.map { it.second }}

How It Works

Key Insight

We need the k most frequent elements from an array. A brute-force sort of all elements by frequency would take O(n log n). Instead, we use a two-phase approach: first count frequencies in O(n), then maintain a min-heap of size k to efficiently select the top k elements in O(n log k).

Phase 1: Frequency Counting

Iterate through the input array and build a frequency map (hash map) counting how many times each element appears. This takes O(n) time with a single pass. For example, in [1,1,1,2,2,3] we get {1: 3, 2: 2, 3: 1}.

Phase 2: Heap Selection

  • Initialize an empty min-heap (ordered by frequency).
  • For each (element, frequency) pair in the frequency map, push it onto the heap.
  • If the heap size exceeds k, pop the minimum element (the one with the lowest frequency). This ensures the heap always contains the k highest-frequency elements seen so far.
  • After processing all entries, the heap contains exactly the top k frequent elements.

Why a Min-Heap?

A min-heap lets us efficiently discard the least frequent element whenever the heap grows beyond size k. The elements that remain are guaranteed to have the highest frequencies. If we used a max-heap, we would pop the most frequent elements instead — the opposite of what we want.

Complexity

Time O(n log k)
Space O(n)

Counting frequencies takes O(n). Iterating over at most n unique elements and performing heap push/pop (each O(log k)) gives O(n log k). Since k ≤ n, this is better than sorting when k is small. Space is O(n) for the frequency map plus O(k) for the heap.