150NeetCode 150

70.Find Median from Data Stream

HardBlind 75Heap / Priority Queue ยท 7/7

Problem

The median is the middle value of a sorted list; for an even count it is the mean of the two middle values. Implement MedianFinder:

  • MedianFinder() initializes the object.
  • void addNum(int num) adds an integer from the stream.
  • double findMedian() returns the median of all numbers added so far (answers within 10^-5 are accepted).

Examples

Input:  ["MedianFinder","addNum","addNum","findMedian","addNum","findMedian"]
        [[],[1],[2],[],[3],[]]
Output: [null,null,null,1.5,null,2.0]
Explanation: [1,2] -> (1+2)/2 = 1.5; [1,2,3] -> 2.
Input:  ["MedianFinder","addNum","findMedian","addNum","findMedian","addNum","findMedian"]
        [[],[5],[],[-1],[],[10],[]]
Output: [null,null,5.0,null,2.0,null,5.0]
Explanation: [5] -> 5; [-1,5] -> 2; [-1,5,10] -> 5.

Constraints

  • -10^5 <= num <= 10^5
  • There is at least one element before findMedian is called.
  • At most 5 * 10^4 calls in total to addNum and findMedian.

๐Ÿ’ก 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, with sizes equal or the lower half one bigger. Then the median is the top of the lower heap (odd count) or the average of both tops (even count): O(log n) to add, O(1) to query.

Brute Force (Sort on Query)

TimeO(1) for addNum; O(n log n) for findMedian.SpaceO(n).

Intuition

Append every number to a list. When asked for the median, sort a copy and read the middle.

Algorithm

  1. addNum: list.add(num).
  2. findMedian: sort the list; if size is odd return list[n/2], else average list[n/2 - 1] and list[n/2].

Visualization

add 5, add -1, add 10 -> list [5,-1,10]
findMedian: sort -> [-1,5,10] -> n = 3 odd -> list[1] = 5

Code

java
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

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

    public MedianFinder() {
    }

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

    public double findMedian() {
        Collections.sort(list); // re-sort on every query
        int n = list.size();
        if (n % 2 == 1) {
            return list.get(n / 2);
        }
        return (list.get(n / 2 - 1) + list.get(n / 2)) / 2.0;
    }
}

Complexity

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

Complexity Comparison

Approach addNum findMedian Space
Sort on Query O(1) O(n log n) O(n)
Sorted List + Binary Insertion O(n) O(1) O(n)
Two Heaps O(log n) O(1) O(n)

Common Pitfalls

  • Integer division: (a + b) / 2 truncates โ€” divide by 2.0 to get 1.5.
  • Only balancing sizes but not ordering: pushing straight into the smaller heap can leave low.peek() > high.peek().
  • Comparing boxed Integer tops with ==, which compares references for values outside [-128, 127].
  • Follow-up: if all numbers are in [0, 100], a 101-bucket count array gives O(1) add and O(100) median.