[算法]返回中位数
题目
设计一个数据结构,使其能够在接收一个数据流时(数据流全部为整数),动态的返回已经接收到数据的中位数
思路
设计一个大顶堆B,一个小顶堆S,第一个数使其进入B,然后把这个数作为比较的对象,大于这个数使其进入S,小于这个数进入B,每一次进入操作后,执行调整操作,如果两个堆的size之差大于2,进行调整,pop堆顶元素进入另一个堆,这个思路有点像AVL树的思路
实现
package MyExc;
import java.util.Comparator;
import java.util.PriorityQueue;
//大根堆
class MaxIntegerHeap implements Comparator<Integer>{
@Override
public int compare(Integer o1, Integer o2) {
return o2.compareTo(o1);
}
}
public class MedianHolder {
private PriorityQueue<Integer> heap1 = new PriorityQueue<>(new MaxIntegerHeap());
private PriorityQueue<Integer> heap2 = new PriorityQueue<>(/*new MaxIntegerHeap()*/);
private int com;
public void push(int data){
if(heap1.isEmpty()&&heap2.isEmpty()){
heap1.add(data);
com = data;
}else{
if(data<=com){
heap1.add(data);
}else if(data>com){
heap2.add(data);
}
}
adjust(heap1,heap2);
}
private void adjust(PriorityQueue<Integer> heap1, PriorityQueue<Integer> heap2) {
if(heap1.size()-heap2.size()>1){
heap2.add(heap1.poll());
}else if(heap2.size()-heap1.size()>1){
heap1.add(heap2.poll());
}
}
public float getMedian(){
if(heap1.size()==heap2.size()){
return (float)(heap1.poll()+heap2.poll())/2;
}else if(heap1.size()>heap2.size()){
return heap1.poll();
}else{
return heap2.poll();
}
}
}
测试代码
package MyExc;
public class Test {
@org.junit.Test
public void run(){
MedianHolder medianHolder = new MedianHolder();
medianHolder.push(1);
medianHolder.push(2);
medianHolder.push(3);
medianHolder.push(4);
medianHolder.push(5);
medianHolder.push(6);
medianHolder.push(7);
medianHolder.push(1000);
System.out.println(medianHolder.getMedian());
}
}
改良思路
我目前使用的是第一个数始终作为比较的参照物,似乎动态调节比较合理,把B堆的堆顶作为比较的参照物比较合理