题目描述
如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。
核心思路:
1.维护一个大顶堆,一个小顶堆,且保证两点:
1)小顶堆里的全大于 大顶堆里的;
2)2个堆个数的差值小于等于1
2.当insert的数字个数为奇数时:使小顶堆个数比大顶堆多1;
当insert的数字个数为偶数时,使大顶堆个数跟小顶堆个数一样。
3.那么当总数字个数为奇数时,中位数就是小顶堆堆头;
当总数字个数为偶数时,中卫数就是 2个堆堆头平均数
import java.util.PriorityQueue;
import java.util.Comparator;
public class Solution {
PriorityQueue<Integer>minheep = new PriorityQueue<>();
PriorityQueue<Integer>maxheep = new PriorityQueue<>(15,new Comparator<Integer>() {
public int compare(Integer integer1,Integer integer2) {
return integer2.compareTo(integer1);//这样输出的结果就是相反的,变成了大根堆
}
});
int count = 0;
public void Insert(Integer num) {
count++;
if(count%2==1){
maxheep.offer(num);//先用大顶堆过滤一遍
minheep.offer(maxheep.poll());
}else {
minheep.offer(num);//先用小顶堆过滤一遍
maxheep.offer(minheep.poll());
}
}
public Double GetMedian() {
if(count%2==0)return (minheep.peek()+maxheep.peek())/2.0;
return (double)minheep.peek();
}
}
首先介绍下优先队列的性质(选自 JDK API)
优先队列是一个基于优先级堆的无界优先级队列。优先级队列的元素按照其自然顺序进行排序,或者根据构造队列时提供的 Comparator 进行排序,具体取决于所使用的构造方法。优先级队列不允许使用 null 元素。依靠自然顺序的优先级队列还不允许插入不可比较的对象(这样做可能导致 ClassCastException)。
此队列的头 是按指定排序方式确定的最小 元素。如果多个元素都是最小值,则头是其中一个元素——选择方法是任意的。队列获取操作 poll、remove、peek 和 element 访问处于队列头的元素。
优先级队列是无界的,但是有一个内部容量,控制着用于存储队列元素的数组大小。它通常至少等于队列的大小。随着不断向优先级队列添加元素,其容量会自动增加。无需指定容量增加策略的细节。
此类及其迭代器实现了 Collection 和 Iterator 接口的所有可选 方法。方法 iterator() 中提供的迭代器不 保证以任何特定的顺序遍历优先级队列中的元素。如果需要按顺序遍历,请考虑使用 Arrays.sort(pq.toArray())。