How do I find the median of numbers in linear time using heaps?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
Heaps are the standard solution for maintaining a running median in a stream, but they are not the right tool if your goal is a strict one-shot O(n) median for a fixed array. That distinction is important because the phrase "linear time using heaps" mixes two different problems.
For a stream, two heaps give excellent incremental performance: O(log n) per insertion and O(1) median lookup. For a single static array where you want true linear-time selection, quickselect is the usual answer instead.
The Two-Heap Streaming Median Pattern
The classic heap approach keeps:
- a max-heap for the lower half of the numbers
- a min-heap for the upper half of the numbers
In Python, heapq is a min-heap, so the lower heap is often simulated by pushing negative values:
This is the right solution when numbers arrive one by one and you need the median after each insertion.
Why This Is Not Strict O(n) for a Static Input
If you already have all n numbers and insert them one at a time into heaps, each insertion costs O(log n). That makes the total time O(n log n), not O(n).
So heaps are efficient, but not linear-time in the strict asymptotic sense for the one-shot median problem.
That is the core correction behind this question: heaps are excellent for dynamic medians, not for proving linear-time selection on a fixed batch of numbers.
If You Need True Linear-Time Selection
For a static array, use a selection algorithm such as quickselect. Quickselect has expected O(n) time and finds the kth order statistic directly without maintaining heaps.
A simple quickselect implementation for the middle element looks like this:
This is the more appropriate direction if the question is really about linear-time median selection for a fixed set.
Pick the Right Algorithm for the Real Problem
Use heaps when:
- numbers arrive incrementally
- you need the median after each insertion
- you want a stable online data structure
Use selection algorithms when:
- all numbers are already available
- you need one median, not a running median
- the time target is strict linear selection rather than online maintenance
That distinction saves a lot of confusion in interviews and algorithm discussions.
Common Pitfalls
- Calling the two-heap streaming approach "linear time" for a fixed batch of
ninserted values. - Using heaps when the real requirement is one-shot selection from a static array.
- Forgetting that Python's
heapqis a min-heap and a max-heap needs negation. - Failing to rebalance the two heaps, which breaks the median invariant.
- Confusing expected
O(n)quickselect with guaranteedO(n)worst-case selection algorithms.
Summary
- Two heaps are the standard running-median solution, not a strict one-shot linear-time selection algorithm.
- For streaming data, heaps are excellent:
O(log n)insert andO(1)median lookup. - For a static array and one median query, quickselect is the more appropriate linear-time idea.
- The right answer depends on whether the problem is online or offline.
- The important fix is to separate "using heaps well" from "achieving strict linear time."

