Heaps in practice
Use heapq to find the k smallest numbers and build a priority queue for tasks with (priority, name) tuples.
- Use heapq.heappush and heapq.heappop correctly
- Implement find_k_smallest using a negated-value max-heap of size k
- Build a priority queue for tasks using (priority, name) tuples
Two patterns you will reach for often: the top-K heap and the task priority queue. Read through the code, adjust the inputs, and re-run to build intuition.
find_k_smallest and a task priority queue
Why negate for a max-heap
heapq only provides a min-heap. To track the largest of k candidates (so
we can replace it when a smaller number comes along), we need a max-heap. The
trick: store -x instead of x. The smallest negative is the largest
original value. Negate on push, negate on pop.
heapreplace(heap, item) is a combined pop-then-push that is slightly faster
than calling them separately — use it inside the scan loop.
The tie-breaking counter
If two tasks have the same priority, comparing (1, "fix bug") and
(1, "respond to alert") would try to compare the strings, which works for
strings but breaks for arbitrary objects. The counter inserted as the second
tuple element guarantees a unique, ordered tie-break and avoids any comparison
on the task name itself.
For Dijkstra's algorithm, replace the task name with a (distance, node)
tuple. The heap always gives you the unvisited node with the smallest known
distance — the same pattern as the priority queue here, just with graph nodes
instead of task names.
Where to go next
Next: lab — structure problems — four problems where you choose the right data structure: a min-stack, level-order traversal, k most frequent, and first unique character.
Heaps and priority queues
Understand the min-heap property, O(log n) push and pop, and why the top-K pattern uses a heap instead of a full sort.
Lab: structure problems
Four problems, each solved cleanly by a different data structure — min-stack, level-order traversal, k most frequent, and first unique character.