65.数据流的中位数
题目描述:
如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。我们使用Insert()方法读取数据流,使用GetMedian()方法获取当前读取数据的中位数。
思路分析:
由于数据流的数据量是实时变化的,我们想取已经出现数据中的中位数,可以设置一个大顶堆和一个小顶堆,如果数据数目为偶数,那么中位数就是两个堆顶元素和的一半。如果数据数目为奇数,那么中位数就为大顶堆的堆顶元素,我们在插入元素的过程中要始终保证大顶堆中的元素小于等于小顶堆中的元素。因此如果我们想往大顶堆中插入数据,先将数据插入小顶堆,然后将小顶堆的堆顶元素插入大顶堆。同样的如如果我们想往小顶堆中插入数据,先将数据插入大顶堆,然后将大顶堆的堆顶元素插入大顶堆。
代码:
import java.util.Comparator;
import java.util.PriorityQueue;
import java.util.Comparator;
public class Solution {
private int count=0;
private PriorityQueue<Integer>minHeap=new PriorityQueue<>();
private PriorityQueue<Integer>maxHeap=new PriorityQueue<>(11,new Comparator<Integer>(){
@Override
public int compare(Integer o1,Integer o2){
return o2.compareTo(o1);
}
});
public void Insert(Integer num) {
count++;
if(count%2==0){ //为偶时放进小顶堆
maxHeap.offer(num);
minHeap.offer(maxHeap.poll());
}else{ //为奇是放进大顶堆
minHeap.offer(num);
maxHeap.offer(minHeap.poll());
}
}
public Double GetMedian() {
if(count==0)
throw new RuntimeException();
Double res;
if(count%2==0)
return res=(maxHeap.peek()+minHeap.peek())/2.0;
else
return res=(double)maxHeap.peek();
}
}