剑指offer提供了许多思路:
(1)直接插入&快排partition()方法寻找第k个数字;
(2)插入排序或链表&直接获取中位数;
(3)二叉搜索树(结点添加子树结点数量的字段);
(4)平衡二叉搜索树;
(5)利用最大堆与最小堆,分别储存数据流中较大的一半数字和较小的一半数字。
采用思路:最大堆与最小堆,使用java中的PriorityQueue实现两个堆,在插入时需要比较两个堆的元素数量以及待插入元素和堆顶元素的大小关系,对两个堆进行调整。
//变量定义:最小堆,最大堆
public static PriorityQueue<Integer> minHeap=new PriorityQueue<>();
public static PriorityQueue<Integer> maxHeap=new PriorityQueue<>(
new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o2-o1;
}
});
//插入操作
public static void Insert(Integer num) {
//两个堆都为空
if(minHeap.size()==0&&maxHeap.size()==0){
minHeap.add(num);
}
//最小堆不为空,最大堆为空,将num与最小堆顶元素比较
else if(minHeap.size()!=0&&maxHeap.size()==0){
if(num>minHeap.peek()){
maxHeap.add(minHeap.poll());
minHeap.add(num);
}
else{
maxHeap.add(num);
}
}
//两个堆都不为空,首先使最小堆元素数量小于等于最大堆元素数量,将最大堆顶元素与待插入元素中较大的插入最小堆,另一个元素插入最大堆
else{
if(minHeap.size()>maxHeap.size()){
maxHeap.add(minHeap.poll());
}
if(num>=maxHeap.peek()){
minHeap.add(num);
}
else if(num<maxHeap.peek()){
minHeap.add(maxHeap.poll());
maxHeap.add(num);
}
}
}
//获取当前数据流的中位数
public static Double GetMedian() {
if(minHeap.size()==0&&maxHeap.size()==0){
return -1.0;
}
else if(minHeap.size()!=0&&maxHeap.size()==0){
return (double)minHeap.peek();
}
else{
if(minHeap.size()==maxHeap.size()){
return (double) (minHeap.peek()+maxHeap.peek())/2;
}
return (double) minHeap.peek();
}
}