如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。
例如,
[2,3,4] 的中位数是 3
[2,3] 的中位数是 (2 + 3) / 2 = 2.5
设计一个支持以下两种操作的数据结构:
void addNum(int num) - 从数据流中添加一个整数到数据结构中。
double findMedian() - 返回目前所有元素的中位数。
1、
class MedianFinder {
/** initialize your data structure here. */
Queue<Integer> A,B;
public MedianFinder() {
//小顶堆,保留较大的部分
A = new PriorityQueue<>();
//大顶堆,保留较小的部分
B = new PriorityQueue<>((o1,o2)->(o2-o1));
}
public void addNum(int num) {
if(A.size() == B.size()){
B.add(num);
A.add(B.poll());
}else{
A.add(num);
B.add(A.poll());
}
}
public double findMedian() {
return (A.size() == B.size()) ? (A.peek()+B.peek())/2.0 : A.peek();
}
}
/**
* Your MedianFinder object will be instantiated and called as such:
* MedianFinder obj = new MedianFinder();
* obj.addNum(num);
* double param_2 = obj.findMedian();
*/
执行用时:67 ms, 在所有 Java 提交中击败了41.89%的用户
内存消耗:52.6 MB, 在所有 Java 提交中击败了18.18%的用户
通过测试用例:18 / 18
2、
class MedianFinder {
PriorityQueue<Integer> big;
PriorityQueue<Integer> small;
public MedianFinder() {
big = new PriorityQueue<>((a,b)->b-a);
small = new PriorityQueue<>();
}
public void addNum(int num) {
int size1 = big.size();
int size2 = small.size();
if(size1 == size2){
if( small.isEmpty() || num <= small.peek()){
big.add(num);
}else{
big.add(small.poll());
small.add(num);
}
}else{
if(big.peek() <= num){
small.add(num);
}else{
small.add(big.poll());
big.add(num);
}
}
}
public double findMedian() {
int size1 = big.size();
int size2 = small.size();
if(size1 == size2){
return (small.peek()+big.peek())/2.0;
}else{
return big.peek();
}
}
}
/**
* Your MedianFinder object will be instantiated and called as such:
* MedianFinder obj = new MedianFinder();
* obj.addNum(num);
* double param_2 = obj.findMedian();
*/
执行用时:95 ms, 在所有 Java 提交中击败了92.93%的用户
内存消耗:59.9 MB, 在所有 Java 提交中击败了40.48%的用户
通过测试用例:21 / 21