As asked
Implement a data structure that supports two operations: addNum(int num) adds a number from a data stream, and findMedian() returns the median of all numbers added so far. The solution must support both operations in better than O(n) time.
Sample answer outline
The canonical solution uses two heaps: a max-heap for the lower half of numbers and a min-heap for the upper half. After each insertion, rebalance so the heaps differ in size by at most one. findMedian returns the top of the larger heap (odd total) or the average of both tops (even total). addNum is O(log n) and findMedian is O(1). Candidates should handle the rebalancing invariant correctly and consider edge cases like a single element.
Reference implementation (python)
import heapq
class MedianFinder:
def __init__(self):
self.lo = [] # max-heap (negate values)
self.hi = [] # min-heap
def addNum(self, num: int) -> None:
heapq.heappush(self.lo, -num)
# move largest of lo to hi
heapq.heappush(self.hi, -heapq.heappop(self.lo))
# rebalance sizes
if len(self.hi) > len(self.lo):
heapq.heappush(self.lo, -heapq.heappop(self.hi))
def findMedian(self) -> float:
if len(self.lo) > len(self.hi):
return -self.lo[0]
return (-self.lo[0] + self.hi[0]) / 2.0Expect these follow-ups
- How would you extend this to return the p90 percentile instead of the median?
- If numbers arrive from multiple Spark partitions in parallel, how would you compute the approximate median at scale?