试题:
如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。我们使用Insert()方法读取数据流,使用GetMedian()方法获取当前读取数据的中位数。
代码:
中位数处于数组的最中间,并且数组左边的数要小于中位数,而数组右边的数要大于中位数。因此我们可以构造两个集合分别存储左边和右边的数。问题是当新来一个数时该如何快速的插入到左边或者右边?假设我们插入左边,这时候为了维护两个集合数量上的相等,我们把左边的最大数弹出放入到右边,同理对于右边。那么左边的集合具有以下特点:左边的数全小于右边的数;弹出时应该能够快速找到左边数的最大值。那么大顶堆很符合我们的情况。
import java.util.*;
public class Solution {
private int count = 0;
private PriorityQueue<Integer> minHeap = new PriorityQueue<>();
private PriorityQueue<Integer> maxHeap = new PriorityQueue<Integer>(1, new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o2 - o1;
}
});
public void Insert(Integer num) {
if ( (count&1) == 1) {
maxHeap.offer(num);
int filteredMaxNum = maxHeap.poll();
minHeap.offer(filteredMaxNum);
} else {
minHeap.offer(num);
int filteredMinNum = minHeap.poll();
maxHeap.offer(filteredMinNum);
}
count++;
}
public Double GetMedian() {
if ( (count&1) == 0) {
return new Double((minHeap.peek() + maxHeap.peek())/2.0 );
} else {
return new Double(maxHeap.peek());
}
}
}