Coding interview problems โบ Heaps & Top-K
๐บ Heaps & Top-K Hard
Find Median from Data Stream
Find Median from Data Stream with two heaps: a max-heap for the lower half and a min-heap for the upper half, O(log n) add, O(1) median. Tested Python, visual.
Also searched as: running median using two heaps ยท median of a stream ยท two heaps pattern
Try it live Free
Binary Heap & Priority Queue
Practise push and pop-min in the heap lab and notice that only the root is cheap to read; this design uses two heaps so the two middle values are always sitting at the roots.
The problem
Design a class that accepts numbers one at a time with add_num(x) and can report the median of everything added so far with find_median(). For an even count, the median is the average of the two middle values.
The key insight
Split the numbers into a lower half and an upper half. Keep the lower half in a max-heap (its root is the largest small number) and the upper half in a min-heap (its root is the smallest big number). If the halves stay balanced in size, the median is one root or the average of both roots.
bisect.insort gives an O(1) median but O(n) insertion, because elements must shift.Step-by-step approach
- Keep
lowas a max-heap (store negatives) andhighas a min-heap. - To add
x, push it ontolow, then move the largest oflowintohigh; this guarantees every value inlowis at most every value inhigh. - If
highnow has more elements thanlow, move its smallest back tolow. - So
lowalways has the same number of elements ashigh, or one more. - Median: if
lowis bigger, return its root; otherwise return the average of both roots.
Python solution
import heapq
class MedianFinder:
def __init__(self):
self.low = [] # max-heap (negated): smaller half
self.high = [] # min-heap: larger half
def add_num(self, x):
heapq.heappush(self.low, -x)
heapq.heappush(self.high, -heapq.heappop(self.low)) # keep order
if len(self.high) > len(self.low): # keep sizes
heapq.heappush(self.low, -heapq.heappop(self.high))
def find_median(self):
if len(self.low) > len(self.high):
return float(-self.low[0])
return (-self.low[0] + self.high[0]) / 2Complexity
Each add does a constant number of heap pushes and pops, O(log n) each. Reading the median only looks at the two roots.
Common mistakes
- Forgetting to negate values when pushing to and reading from the max-heap, which silently turns it into a min-heap.
- Balancing only the sizes but not the order, so a large value ends up in the lower half and the roots no longer bracket the median.
- Using integer division for the even case, which returns 2 instead of 2.5.
Frequently asked questions
What is the time and space complexity of the two-heap median?
add_num is O(log n), find_median is O(1), and the two heaps together store all n numbers, O(n) space.
Why a max-heap for the lower half?
You need the largest of the small numbers at a glance, and a max-heap keeps it at the root. Symmetrically, the min-heap keeps the smallest of the large numbers at its root.
What if all numbers are in a small range, like 0 to 100?
Keep a count array of size 101 and walk it to find the middle, which is O(100) per query and O(1) per add.
How do I handle a sliding window median?
Use the same two heaps with lazy deletion (mark removed values and discard them when they reach a root), or a sorted container that supports removal.
Preparing for placements?
Take the 2-minute readiness check to find your weak patterns, then follow the placement path from DSA core to system design.
All coding interview problems More Heaps & Top-K Binary Heap & Priority Queue lab Placement prep guides
Problem statements on this site are written in our own words. Problem names are the common names used across interview-prep communities; BitBootcamp is an independent learning platform and is not affiliated with LeetCode or any company that asks these questions.