题目描述:
如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。我们使用Insert()方法读取数据流,使用GetMedian()方法获取当前读取数据的中位数。
思路:
利用PriorityQueue分别建立大顶堆和小顶堆,由于大顶堆是从大到小顺序排列的,小顶堆是从小到大排列的,将数据流的数分成两部分,较大的一部分放在小顶堆,较小的一部分放在大顶堆,所以大顶堆的根结点的值与小顶堆根结点的值,在数据流中应该是中间相邻的两个数。
规则:从count=0开始,对数据流num划分,每次划分到minHeap或者maxHeap中,
若count为偶数,将num分到大顶堆中(maxHeap.offer(num)),再把大顶堆中最大的值poll()出,放到小顶堆minHeap中;
若count为奇数,将num分到小顶堆中(minHeap.offer(num)),再把小顶堆中最小的值poll()出,放到大顶堆maxHeap中;
对count++;
最后一句count的值判定中位数取值。
只需对数据流中数据个数进行统计,若为偶,则中位数为大顶堆root值与小顶堆root值的平均值;若为奇,则中位数为小顶堆root值。
实现中的问题:
1、大顶堆的建立规则
2、最后输出的值类型为double,需要new Double()。
代码实现:
import java.util.PriorityQueue; import java.util.Comparator; public class Solution { //利用PriorityQueue建立大小顶堆 //小顶堆 private PriorityQueue<Integer> minHeap=new PriorityQueue<Integer>(); //大顶堆 private PriorityQueue<Integer> maxHeap=new PriorityQueue<Integer>(15,new Comparator<Integer>(){ @Override public int compare(Integer o1,Integer o2){ return o2-o1; } }); int count=0; //用来记录当前的奇偶 public void Insert(Integer num) { if(count%2==0){ maxHeap.offer(num); int max=maxHeap.poll(); minHeap.offer(max); }else{ minHeap.offer(num); int min=minHeap.poll(); maxHeap.offer(min); } count++; } public Double GetMedian() { if(count%2==0){ return new Double(minHeap.peek()+maxHeap.peek())/2; }else{ return new Double(minHeap.peek()); } } }