DSA Heaps

Find Median from a Data Stream

Maintain the running median with two heaps — max-heap for the lower half, min-heap for the upper half.

Hard
Time O(log n) per add Space O(n)
LeetCode
5 min read
heaps design

Problem#

Design MedianFinder supporting addNum(int) and findMedian() that returns the median of all numbers added so far.

Examples#

  • addNum(1); addNum(2); findMedian() → 1.5; addNum(3); findMedian() → 2.0

Constraints#

  • Up to 5 * 10^4 ops.

Hints#

Hint 1
Split the stream into two halves at the median; use a max-heap for the lower and a min-heap for the upper.

Approach#

Two heaps with sizes differing by at most 1: lo is a max-heap holding the smaller half, hi is a min-heap holding the larger half. On addNum: route to lo, then push the top of lo into hi to rebalance, and rebalance sizes if hi > lo.

Solution#

Median Finder
class MedianFinder {
priority_queue<int> lo; // max-heap
priority_queue<int, vector<int>, greater<int>> hi; // min-heap
public:
void addNum(int n) {
lo.push(n);
hi.push(lo.top()); lo.pop();
if (hi.size() > lo.size()) { lo.push(hi.top()); hi.pop(); }
}
double findMedian() {
return lo.size() > hi.size() ? lo.top() : (lo.top() + hi.top()) / 2.0;
}
};

Editorial#

The invariant: |lo| - |hi| ∈ {0, 1} and max(lo) <= min(hi). Routing through hi first guarantees the maximum of lo doesn’t exceed the minimum of hi. The constant-size rebalance keeps lo at most 1 larger than hi. Median is the top of lo on odd sizes, average of the two tops on even.

Complexity#

  • Time: O(log n) per addNum; O(1) for findMedian.
  • Space: O(n).

Concept revision#

Search ESC

Keyboard shortcuts

Shortcuts are disabled while typing in inputs.