Android & iPhone apps are coming soon. Log in for a plan and reminders made for you โ†’

Know this before you start: โ€œKeep only the k best items in a heapโ€

Keeping only the k best with a heap

For the k largest, keep a min-heap of size k: whenever it grows past k, pop the smallest. What's left are the k largest. O(n log k).

The idea

Sorting everything to take the top k costs O(n log n). A heap that never holds more than k items is cheaper when k is small.

For the k largest use a MIN-heap: its top is the weakest of the current best k, the one to kick out when something better arrives. At the end, the top is the k-th largest overall.

See it step by step

The 2 largest of [3, 2, 1, 5, 6, 4]

  1. push 3, 2 โ†’ {2, 3}
  2. push 1 โ†’ pop 1. push 5 โ†’ pop 2 โ†’ {3, 5}. push 6 โ†’ pop 3 โ†’ {5, 6}. push 4 โ†’ pop 4.
  3. Left: {5, 6}. The 2nd largest is the top: 5.

In code (Python)

import heapq

def k_largest(nums, k):
    heap = []
    for x in nums:
        heapq.heappush(heap, x)
        if len(heap) > k:
            heapq.heappop(heap)     # drop the smallest of the k + 1
    return sorted(heap, reverse=True)

print(k_largest([3, 2, 1, 5, 6, 4], 2))   # [6, 5]
print(heapq.nlargest(2, [3, 2, 1, 5, 6, 4]))   # [6, 5], the built-in

O(n log k) time, O(k) space.

When you'll use it

  • k largest / smallest / closest / most frequent, k-th largest, streams where data keeps arriving.

Common mistakes

  • Using a max-heap for the k largest (it keeps the wrong end).
  • Pushing all n items then popping k (O(n log n), O(n) space).

Practise it: Heap / Priority Queue

Go further