最小堆 数据流中的中位数
实现Insert()方法读取数据流,使用GetMedian()方法获取当前读取数据的中位数。
思路:
采用一个最大堆maxHeap,一个最小堆minHeap
最大堆的数据都小于最小堆的数据,同时维护2个堆的数据数目count相等,或最小堆的数目比最大堆大1
这样中位数一定是2个堆的堆顶元素平均值,或者一定位于最小堆的堆顶
细节:
如果当前2个堆数目相等,那么向最小堆插入数据之前,需要先到最大堆过滤一遍,以确保最大堆中最大值放入最小堆
public class Solution {
private int count = 0;
private PriorityQueue<Integer> minHeap = new PriorityQueue<>();
private PriorityQueue<Integer> maxHeap = new PriorityQueue<Integer>(15, new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o2 - o1;
}
});
//一些约束 小根堆的所有数据都大于大根堆
//2个堆的 数目相等或小根堆比大根堆大1
//这样保证中位数,总是小根堆堆顶,或者2者堆顶的平均值
public void Insert(Integer num) {
if(count&1==1) //若为奇数
{
minHeap.offer(num);//先加入小根堆
int min_=minHeap.poll();//取出小根堆最小值
maxHeap.offer(min_);
}
else
{
//总是要保证 minHeap的所有数据大于maxHeap
//所以加入到一个堆时,总是先到另一个堆 过滤一波
maxHeap.offer(num);
int max_=maxHeap.poll();
min.offer(max_);
}
count++;
}
public Double GetMedian() {
if(count&1==1) //奇数个
return new Double(minHeap.peek());//取小根堆堆顶
else
return new Double((minHeap.peek()+maxHeap.peek())/2);
}
}
采用Java中的PriorityQueue优先队列数据结构,默认是最小堆,若需要最大堆,则实现一个Comparator比较器