要拿到中位数就需要得到中间的一个或者两个数。
思路:把数据分成左右两部分,左右两边的数据量不超过1,左边小于右边,左边拿到最大值,右边拿到最小值,这两个数肯定可以得到中位数。
那么左边可以用大根堆,右边用小根堆。如果在有数进来的时候如果小于大根堆的堆顶,就进入大根堆,如果大于等于大根堆的堆顶,就进入小根堆。当加入数据两个堆的大小超过1的时候,数据大的那个堆弹出堆顶元素到另外一个堆中。
//大根堆比较器
public static class bigComparator implements Comparator<Integer>{
@Override
public int compare(Integer o1, Integer o2) {
// TODO Auto-generated method stub
return o2 - o1;
}
}
public static void Middle(int[] arr,PriorityQueue<Integer> small,PriorityQueue<Integer> big) {
//第一个数随便加不影响
big.add(arr[0]);
for(int i=1;i<arr.length;i++) {
if(arr[i]<=big.peek()) {//如果小于大根堆的堆顶,就加入大根堆
big.add(arr[i]);
}else {
small.add(arr[i]);
}
//保证两个堆的大小差在1之内
if(small.size() - big.size() > 1) {
big.add(small.poll());
}
if(big.size() - small.size() > 1) {
small.add(big.poll());
}
}
}
public static void main(String[] args) {
int[] arr = {3,5,7,4,6,9,1};
PriorityQueue<Integer> big = new PriorityQueue<Integer>(new bigComparator());
PriorityQueue<Integer> small = new PriorityQueue<Integer>();
Middle(arr, small, big);
while(!big.isEmpty()) {
System.out.println(big.poll());
}
while(!small.isEmpty()) {
System.out.println(small.poll());
}
}