leetcode-数据流中的中位数
题目链接:添加链接描述
题目大意就是有一个数组,要求出来这个数组排过序后的中位数,乍一看其实很简单,直接排序后根据元素的总个数取中间两个数的平均数或者中间的数即可,不过还是挺现实的,这样做不太行,因为这个数组的数据量有一点点大,所以要换一个思路。
首先介绍一下小顶堆,那个东西理论上是一个排过序的完全二叉树,在Java里面可以用PriorityQueue来代替,其实叫人家优先队列更合适,加入其中的元素,再取出队头时会按照从小到大的顺序出队,大顶堆的出队顺序相反,所以来说,可以将原先的原数组分成两部分,数值较大的一部分使用小根堆存储,数值较小的使用大根堆存储,如此,根据二者的队头元素就可以实现中位数的求取
//让A成为一个小顶堆,存储值比较大的部分,数据从小到大存储
//让B成为一个大顶堆,存储值比较小的部分,数据从大到小存储
//最后的效果就是,在A和B的栈顶,存储着原先数组的中位数
Queue<Integer> queueA = new PriorityQueue<Integer>();
Queue<Integer> queueB = new PriorityQueue<Integer>((x, y) -> (y - x));
/** initialize your data structure here. */
public MedianFinder() {
}
public void addNum(int num) {
//如果元素的个数相同,取较大的数值放入A中
if(queueA.size() == queueB.size()) {
queueB.add(num);
queueA.add(queueB.poll());
}else {
queueA.add(num);
queueB.add(queueA.poll());
}
}
//A: 2, 3
//B: 1
public double findMedian() {
if(queueA.size() == queueB.size()) {
//总数是偶数
double x = queueA.peek();
double y = queueB.peek();
return (x+y)/2.0;
}else {
double x = queueA.size() > queueB.size() ? queueA.peek() : queueB.peek();
return x;
}
}
数据结构真的挺有用,希望后面能一切顺利吧