Find Median from Data Stream

HardTwo Heaps · Design🧩 Two HeapsLeetCode #295 ↗Updated

Problem

Build a class MedianFinder that receives integers one by one through addNum(num) and, at any moment, returns the median of everything seen so far via findMedian(). For an even count the median is the average of the two middle values.
Inputadd(1) add(2) findMedian()Output1.5
Inputadd(3) findMedian()Output2.0

-105 ≤ num ≤ 105  ·  findMedian only after ≥ 1 add  ·  ≤ 5·104 calls  ·  Follow-up: all nums in [0,100]? 99% of them?

Try it yourself

Java
class MedianFinder {
    public void addNum(int num) {
        
    }

    public double findMedian() {
        
    }
}
Your code is saved in this browser.Submit on LeetCode ↗
Key insight
The median only depends on the boundary between the smaller half and the larger half. Keep the smaller half in a max-heap and the larger half in a min-heap; their tops are exactly the middle element(s).
PatternTwo Heaps

Instinct When you need the middle of a changing collection, or best-of-one-pile fed by another pile, split it into a max-heap low half and a min-heap high half.

Memory hack Small fries in a max-heap, big fish in a min-heap; the median lives on the shoreline between them.

Open the Two Heaps guide →

Approaches

Brute ForceStore All, Sort on Query

Time O(1) add, O(n log n) findSpace O(n)

Append each number to a list. When asked for the median, copy and sort the list and read the middle one or two values. Nothing clever is maintained between calls, so every query pays a full sort.

Java
class MedianFinder {
    private final List<Integer> nums = new ArrayList<>();

    public void addNum(int num) { nums.add(num); }

    public double findMedian() {
        List<Integer> s = new ArrayList<>(nums);
        Collections.sort(s);
        int n = s.size();
        if (n % 2 == 1) return s.get(n / 2);
        return (s.get(n / 2 - 1) + s.get(n / 2)) / 2.0;
    }
}

Trivial to write; far too slow when queries are frequent.

At a glance

LevelApproachTimeSpace
Brute ForceStore All, Sort on QueryO(1) add, O(n log n) findO(n)
BetterSorted List + Binary-Search InsertO(n) add, O(1) findO(n)
OptimalTwo Heaps (Max-Heap Low, Min-Heap High)O(log n) add, O(1) findO(n)
Common pitfalls
  • Max-heap via (a, b) -> b - a — overflows for extreme ints; prefer reverseOrder().
  • Integer division (a + b) / 2 — loses the .5; divide by 2.0.
  • Balancing sizes only, without the order check — a big value can end up in low.
Interview tips
  • Draw the two halves as two triangles meeting at the median — heap tops face each other.
  • State both invariants (ordering and size) and show each addNum restores them.
  • Have the bucket-count answer ready for the bounded-range follow-ups.
Pattern
Two heaps → maintain a running median / k-th boundary of a dynamic multiset.
My notes saved in this browser