Debugging challengeIntermediate

Top-K with the heap pointing the wrong way

Scenario

A dashboard shows the k highest scores out of n (n up to 10⁸ streamed from disk, k = 100). The current implementation is correct but runs out of memory and is slow. A junior engineer "fixed" the memory issue in top_k_v2, which is now wrong. Diagnose both versions.

Broken
1import heapq
2
3def top_k_v1(scores, k):
4 # correct but heavy
5 heap = []
6 for s in scores:
7 heapq.heappush(heap, -s)
8 return [-heapq.heappop(heap) for _ in range(k)]
9
10
11def top_k_v2(scores, k):
12 # "memory fix" — keeps only k elements
13 heap = []
14 for s in scores:
15 heapq.heappush(heap, -s)
16 if len(heap) > k:
17 heapq.heappop(heap)
18 return sorted((-x for x in heap), reverse=True)
19
20print(top_k_v2([5, 1, 9, 3, 7], 2)) # prints [3, 1], expected [9, 7]

The corrected version appears here once you have revealed everything below.

Your task

  1. Explain why top_k_v1 is correct and what its time and space costs are for n = 10⁸, k = 100.
  2. Explain exactly why top_k_v2 returns the two *smallest* values.
  3. Write the correct bounded-size version and state the invariant the heap maintains.
  4. Compare with heapq.nlargest, sorting, and quickselect. When would you choose each?
DebuggingOptimizationComplexity Analysis

Work it out

Write your analysis before revealing anything. The self-check below compares it against what a strong answer contains.

Reveal

Progressive — each section builds on the previous one.

The bug
Why it happens
The fix
Edge cases
Complexity
What this tests

Self-check

Tick what your analysis covered. Be honest — this feeds your readiness profile.

0/7

Related concepts