用一个最大堆和一个最小堆来记录数据,保证最大堆的数据的最大值小于最小堆的最小值。并且保持两者的数目之差不超过1。这样便可以以 O ( 1 ) O(1) O(1)的时间里找到中位数。
class MedianFinder {
private PriorityQueue<Integer> maxHeap;
private PriorityQueue<Integer> minHeap;
/** initialize your data structure here. */
public MedianFinder() {
// 最大堆和最小堆
maxHeap = new PriorityQueue<>((x, y) -> (y - x));
minHeap = new PriorityQueue();
}
public void addNum(int num) {
// 假如为当前数据数目为奇数,插入最大堆,否则插入最小堆
if(((maxHeap.size() + minHeap.size()) & 1) == 1){
// 保证最大堆的数据永远比最小堆的任意数据小。
if(minHeap.size() > 0 && num > minHeap.peek()){
minHeap.offer(num);
num = minHeap.poll();
}
maxHeap.offer(num);
} else {
if(maxHeap.size() > 0 && num < maxHeap.peek()){
maxHeap.offer(num);
num = maxHeap.poll();
}
minHeap.offer(num);
}
}
public double findMedian() {
int size = minHeap.size() + maxHeap.size();
if(size <= 0)
return 0.0;
double mean;
// 数据个数为偶数,取两者平均值,否则取最小堆堆顶
if((size & 1) == 0)
mean = 1.0 * (minHeap.peek() + maxHeap.peek()) / 2;
else
mean = minHeap.peek();
return mean;
}
}
/**
* Your MedianFinder object will be instantiated and called as such:
* MedianFinder obj = new MedianFinder();
* obj.addNum(num);
* double param_2 = obj.findMedian();
*/