Problem Statement
Find Median from Data Stream - LeetCode
Pattern:
Solution
public class FindMedianinStream295 {
static class MedianFinder {
private PriorityQueue<Integer> lMax;
private PriorityQueue<Integer> rMin;
private double currMedian;
// constructor
public MedianFinder() {
lMax = new PriorityQueue<>(Collections.reverseOrder());
rMin = new PriorityQueue<>();
currMedian = 0;
}
// add num to DS
public void addNum (int num) {
switch (lMax.size() - rMin.size()) {
// l == r
case 0 : {
// add to right
if(num >= currMedian) rMin.add(num);
// add to left
else lMax.add(num);
break;
}
// l > r
case 1 : {
// add to right
if(num >= currMedian) rMin.add(num);
// add to left
else {
// balance heaps
rMin.add(lMax.poll());
// add num to left heap
lMax.add(num);
}
break;
}
// r > l
case -1 : {
// add to right
if(num >= currMedian){
// balance heaps
lMax.add(rMin.poll());
// add to rMin
rMin.add(num);
}
// add to left
else lMax.add(num);
break;
}
}
// update median
findMedian();
//System.out.printf("num :%d , currMedian: %f , lMax: %d, rMin: %d\n", num, currMedian, lMax.peek(), rMin.peek());
}
// find median
public double findMedian (){
int size = lMax.size() + rMin.size();
// even size -> avg of heap peeks
if((size & 1) == 0) currMedian = ((double) lMax.peek()+ (double) rMin.peek())/ (double)2;
// larger heap peek is the median
else if (lMax.size() > rMin.size()) currMedian = lMax.peek();
else currMedian = rMin.peek();
// return median
return currMedian;
}
}
// region MAIN
public static void main(String[] args) {
MedianFinder mf = new MedianFinder();
mf.addNum(1);
mf.addNum(2);
System.out.println(mf.findMedian());
mf.addNum(3);
System.out.println(mf.findMedian());
}
// endregion
}
Output:
1.5
2.0
Notes
- an array can be thought of as to heaps left and right. left heap is a maxHeap whose greatest element is less than the median, and right heap is a min heap whose smallest element is larger than the median.
- insert element in the left or right heap depending on if it is greater or smaller than median
- update median
- repeat till needed
- inserting elements is not super straightforward. the idea is to maintain heaps in such a way that all the elements in the leftMax heap are always less than the currentMedian and the elements in the rightMin heap are always greater than the currentMedian
- So say 2 consecutive elements added are greater than the currentMedian, the median would shift towards the right heap.
- this is why we must always make sure
leftMax.size - rightMin.size <= 1
- Love Babbar Video Explaining Solution