Courses › Coding Interviews › Patterns
Heaps & Top-K
Top-K, k-way merge, running medians and scheduling.
A heap (priority queue) gives you the smallest (or largest) element in O(1) and inserts or removes in O(log n). Reach for one whenever a problem asks for the top K, the k-th something, or repeatedly needs the next smallest item.
When to use it
- Top K / k-th largest — keep a heap of size k
- Merging k sorted lists — the heap holds the current head of each list
- Running median — two heaps
- Scheduling — always process the earliest-ending, highest-priority or cheapest item next
- Shortest paths in weighted graphs (Dijkstra)
Python's heapq
heapq is a min-heap on a plain list. For a max-heap, push negated values. Push tuples to order by a key: (priority, tiebreaker, item).
import heapq
h = []
heapq.heappush(h, (3, "c"))
heapq.heappush(h, (1, "a"))
smallest = heapq.heappop(h) # (1, "a")
heapq.heapify(list_of_items) # O(n)Template: top K with a size-k min-heap
import heapq
def kth_largest(nums, k):
heap = []
for x in nums:
heapq.heappush(heap, x)
if len(heap) > k:
heapq.heappop(heap) # drop the smallest; the k largest remain
return heap[0]O(n log k) time, O(k) space — better than sorting when k ≪ n, and it works on streams.
Template: k-way merge
import heapq
def merge_k_sorted(lists):
heap = [(lst[0], i, 0) for i, lst in enumerate(lists) if lst]
heapq.heapify(heap)
out = []
while heap:
val, i, j = heapq.heappop(heap)
out.append(val)
if j + 1 < len(lists[i]):
heapq.heappush(heap, (lists[i][j + 1], i, j + 1))
return outTemplate: two heaps for a running median
Keep the lower half in a max-heap and the upper half in a min-heap, balanced so their sizes differ by at most one. The median is at the top of one or both.
import heapq
class MedianFinder:
def __init__(self):
self.low, self.high = [], [] # low is a max-heap via negation
def add(self, x):
heapq.heappush(self.low, -x)
heapq.heappush(self.high, -heapq.heappop(self.low))
if len(self.high) > len(self.low):
heapq.heappush(self.low, -heapq.heappop(self.high))
def median(self):
if len(self.low) > len(self.high):
return -self.low[0]
return (-self.low[0] + self.high[0]) / 2[!TIP] Practice Top K Frequent Elements · Find Median from Data Stream · Minimum Meeting Rooms