//方法:大顶堆和小顶堆法
//时间复杂度:nlogn
//空间复杂度:n
import java.util.*;
public class Solution {
//解决方法:堆
//新建大顶堆和小顶堆
private int cnt = 0; //静态计数
// 默认维护小顶堆,放后半段的值
private PriorityQueue<Integer> low = new PriorityQueue<>(); //小顶堆,降序排列
//大顶堆,放前半段的值
private PriorityQueue<Integer> high = new PriorityQueue<>(new Comparator<Integer>(){
@Override
public int compare(Integer o1, Integer o2){
return o2.compareTo(o1);
}
}); //重写compare方法,实现大顶堆,升序排列
public void Insert(Integer num) {
//动态计数
//奇数放在大顶堆,前提是新插入的数要比小顶堆上的数小,否则要放入小顶堆中,
//最后将重排后小顶堆上的数吐出放入大顶堆中
//偶数放在小顶堆,前提是新插入的数要比大顶堆大,否则要放入大顶堆中
//等大顶堆重排后,将大顶堆上的数吐出放入小顶堆中
cnt++; //插入值,自增
//cnt为奇数,新插入的值要放入大顶堆中
if((cnt & 1) == 1){
//判断小顶堆不为空,且新插入的值是否比小顶堆上的值小,那么将num先放入小顶堆中重排序
if(!low.isEmpty() && num > low.peek()){
low.offer(num); //小顶堆重建
num = low.poll(); //弹出根节点的值,重建小顶堆
}
high.offer(num);
}
//cnt为偶数,新插入的值要放在小顶堆中
if((cnt & 1) == 0){
//判断大顶堆为空,且新插入的值小于大顶堆的根节点的值
if(!high.isEmpty() && num < high.peek()){
high.offer(num);
num = high.poll();
}
low.offer(num);
}
}
public Double GetMedian() {
//定义双精度变量存放平均值
double aver = 0;
//cnt为奇数,取大顶堆的根节点的值
if((cnt & 1) == 1){
aver = high.peek();
}
//cnt为偶数,取大顶堆和小顶堆的根节点的平均值
if((cnt & 1) == 0){
aver = (high.peek() + low.peek())/2.0;
}
return aver;
}
}