PracticeNeetCode ↗LeetCode ↗
Design a data structure that accepts integers one at a time from a stream and can report the median of all numbers seen so far at any point, efficiently.
findMedian an O(1) lookup.small, a max-heap (via negated values) for the lower half, and large, a min-heap for the upper half.addNum(val): push into small first, then move small's current max into large — this guarantees every value in large is ≥ every value in small.large bigger than small, move large's min back into small to restore the size balance.findMedian(): if the heaps are equal size, average their two tops; otherwise small is guaranteed to hold one extra element, so return its top directly.Time: O(log n) per addNum, O(1) per findMedian — Space: O(n)
import heapq
class MedianFinder:
def __init__(self):
self.small = [] # max-heap (negated values) — lower half
self.large = [] # min-heap — upper half
def addNum(self, num: int) -> None:
heapq.heappush(self.small, -num)
heapq.heappush(self.large, -heapq.heappop(self.small))
if len(self.large) > len(self.small):
heapq.heappush(self.small, -heapq.heappop(self.large))
def findMedian(self) -> float:
if len(self.small) > len(self.large):
return -self.small[0]
return (-self.small[0] + self.large[0]) / 2How the solution above works, piece by piece.
small is a max-heap (values negated) for the lower half; large is a min-heap for the upper half.addNum pushes into small, then moves small's largest into large. This guarantees every value in small ≤ every value in large.large now has more elements, move its smallest back, so small is always equal in size or one larger.findMedian: with an odd total it's small's top; with an even total it's the average of both tops.addNum is O(log n); findMedian is O(1).Running addNum(1), addNum(2), findMedian(), addNum(3), findMedian():
small may hold one extra element; with an odd count its top is the median.