Heaps & Priority Queues — Complete Interview Guide
Advertisement
What Is a Heap?
A heap is a complete binary tree satisfying the heap property:
- Min-heap: parent ≤ children (root = smallest)
- Max-heap: parent ≥ children (root = largest)
Heaps implement priority queues in O(log n) push/pop, O(1) peek.
Language Heap APIs
# Python — min-heap by default
import heapq
h = []
heapq.heappush(h, val)
heapq.heappop(h) # removes and returns smallest
h[0] # peek min (no removal)
heapq.heapify(lst) # O(n) in-place
# Max-heap: negate values
heapq.heappush(h, -val)
// C++ — max-heap by default
#include <queue>
priority_queue<int> maxH; // max-heap
priority_queue<int, vector<int>, greater<int>> minH; // min-heap
maxH.push(val);
maxH.top(); // peek
maxH.pop();
// Java — min-heap by default
PriorityQueue<Integer> minH = new PriorityQueue<>();
PriorityQueue<Integer> maxH = new PriorityQueue<>(Collections.reverseOrder());
minH.offer(val);
minH.peek(); // O(1)
minH.poll(); // O(log n)
// JavaScript — no built-in heap; implement or use array + sort
// Common pattern: use sorted array for small inputs
// Or implement MinHeap class
class MinHeap {
constructor() { this.h = []; }
push(v) { this.h.push(v); this._bubbleUp(); }
pop() { const top=this.h[0]; const last=this.h.pop(); if(this.h.length){this.h[0]=last;this._sinkDown();} return top; }
peek() { return this.h[0]; }
size() { return this.h.length; }
_bubbleUp() { let i=this.h.length-1; while(i>0){const p=(i-1)>>1;if(this.h[p]<=this.h[i])break;[this.h[p],this.h[i]]=[this.h[i],this.h[p]];i=p;} }
_sinkDown() { let i=0,n=this.h.length; while(true){let min=i,l=2*i+1,r=2*i+2;if(l<n&&this.h[l]<this.h[min])min=l;if(r<n&&this.h[r]<this.h[min])min=r;if(min===i)break;[this.h[i],this.h[min]]=[this.h[min],this.h[i]];i=min;} }
}
7 Core Heap Patterns
Pattern 1 — Top K (Fixed-Size Heap)
Maintain a heap of size K. For K largest: use min-heap (evict smallest). For K smallest: use max-heap.
import heapq
def top_k_largest(nums, k):
return heapq.nlargest(k, nums)
# Manual K-size heap (O(n log k)):
def top_k_manual(nums, k):
heap = []
for n in nums:
heapq.heappush(heap, n)
if len(heap) > k:
heapq.heappop(heap)
return heap # k largest elements
Pattern 2 — K-th Element
def kth_largest(nums, k):
return heapq.nlargest(k, nums)[-1]
# Or: partial sort with min-heap of size k
Pattern 3 — Two Heaps (Median Maintenance)
Keep max-heap (lower half) and min-heap (upper half), balanced within 1.
from heapq import heappush, heappop
lo = [] # max-heap (negate)
hi = [] # min-heap
def add_num(num):
heappush(lo, -num)
heappush(hi, -heappop(lo)) # ensure max(lo) <= min(hi)
if len(lo) < len(hi):
heappush(lo, -heappop(hi))
def find_median():
if len(lo) > len(hi):
return -lo[0]
return (-lo[0] + hi[0]) / 2
Pattern 4 — Merge K Sorted (K-way Merge)
Use min-heap of (value, list_index, element_index).
def merge_k_sorted(lists):
heap = [(lst[0], i, 0) for i, lst in enumerate(lists) if lst]
heapq.heapify(heap)
result = []
while heap:
val, i, j = heapq.heappop(heap)
result.append(val)
if j + 1 < len(lists[i]):
heapq.heappush(heap, (lists[i][j+1], i, j+1))
return result
Pattern 5 — Scheduling / Task Assignment
Use heap to track next available time.
# Assign k workers to tasks; each takes 1 unit; worker available after finish
import heapq
def schedule(tasks, k):
heap = list(range(k)) # availability times (all 0 initially)
heapq.heapify(heap)
for task in tasks:
earliest = heapq.heappop(heap)
heapq.heappush(heap, earliest + task)
return max(heap)
Pattern 6 — Dijkstra / Greedy with Heap
import heapq
def dijkstra(graph, src):
dist = {src: 0}
heap = [(0, src)]
while heap:
d, u = heapq.heappop(heap)
if d > dist.get(u, float('inf')): continue
for v, w in graph[u]:
nd = d + w
if nd < dist.get(v, float('inf')):
dist[v] = nd
heapq.heappush(heap, (nd, v))
return dist
Pattern 7 — Frequency Bucket + Heap
from collections import Counter
import heapq
def top_k_frequent(nums, k):
count = Counter(nums)
# Max-heap by frequency
return heapq.nlargest(k, count.keys(), key=count.get)
Section Problems (421–480)
| # | Title | Difficulty | Pattern |
|---|---|---|---|
| 421 | Kth Largest Element in a Stream | Easy | Top K stream |
| 422 | Last Stone Weight | Easy | Max-heap |
| 423 | Relative Ranks | Easy | Max-heap + sort |
| 424 | Find K Closest Elements | Easy | Heap or binary search |
| 425 | Kth Largest Element in Array | Medium | Quickselect / heap |
| 426 | Top K Frequent Elements | Medium | Frequency + heap |
| 427 | Sort Characters by Frequency | Medium | Frequency + heap |
| 428 | K Closest Points to Origin | Medium | Max-heap top K |
| 429 | Task Scheduler | Medium | Greedy + max-heap |
| 430 | Reorganize String | Medium | Greedy + max-heap |
| 431 | Find Median from Data Stream | Hard | Two heaps |
| 432 | Sliding Window Median | Hard | Two heaps |
| 433 | Merge K Sorted Lists | Hard | K-way merge |
| 434 | Kth Smallest Element in Sorted Matrix | Medium | Heap or BS |
| 435 | Find K Pairs with Smallest Sums | Medium | K-way merge |
| 436 | Ugly Number II | Medium | Multi-way merge |
| 437 | Super Ugly Number | Medium | Multi-way merge |
| 438 | Smallest Range Covering K Lists | Hard | K-way merge |
| 439 | Course Schedule III | Hard | Greedy + max-heap |
| 440 | Maximum CPU Load | Medium | Scheduling heap |
| 441 | Meeting Rooms II | Medium | Scheduling heap |
| 442 | Car Pooling | Medium | Events + heap |
| 443 | Minimum Cost to Connect Sticks | Medium | Min-heap greedy |
| 444 | Process Tasks Using Servers | Medium | Two heaps |
| 445 | Furthest Building You Can Reach | Medium | Min-heap greedy |
| 446 | IPO | Hard | Two heaps |
| 447 | Trapping Rain Water II | Hard | Min-heap BFS |
| 448 | Jump Game VII | Medium | BFS / heap |
| 449 | Swim in Rising Water | Hard | Dijkstra / binary search |
| 450 | Design Twitter | Medium | Heap merge |
| 451–460 | Extended heap / design problems | Mixed | Various |
Advertisement