0%

连续中值

连续中值

随机产生数字并传递给一个方法。你能否完成这个方法,在每次产生新值时,寻找当前所有值的中间值(中位数)并保存。

中位数是有序列表中间的数。如果列表长度是偶数,中位数则是中间两个数的平均值。

例如,

[2,3,4] 的中位数是 3

[2,3] 的中位数是 (2 + 3) / 2 = 2.5

设计一个支持以下两种操作的数据结构:

void addNum(int num) - 从数据流中添加一个整数到数据结构中。
double findMedian() - 返回目前所有元素的中位数。

示例:

addNum(1)
addNum(2)
findMedian() -> 1.5
addNum(3)
findMedian() -> 2

思路

数组分两半,左边建大顶堆维护左半部分的最大值,右边建小顶堆维护右半部分的最小值,两个堆顶的均值就是数组的中值。每次插入数据的时候判断一下:

如果要插入的数据比右边小顶堆堆顶小,则插到左边;
如果要插入的数据比左边大顶堆堆顶大,则插到右边;
如果介于二者中间,也插到右边,

同时要保证右边的小顶堆长度最多比左边的大顶堆大1。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
priority_queue<int, vector<int>, less<int> >bigheap;
priority_queue<int, vector<int>, greater<int> >smallheap;

MedianFinder() {

}

void addNum(int num) {
if(bigheap.size()==0&&smallheap.size()<=1) smallheap.push(num);
else if(num<smallheap.top()) bigheap.push(num);
else if(num>bigheap.top()) smallheap.push(num);
else bigheap.push(num);

if(smallheap.size()>bigheap.size()+1){
bigheap.push(smallheap.top());
smallheap.pop();
}
if(bigheap.size()>smallheap.size()){
smallheap.push(bigheap.top());
bigheap.pop();
}
}

double findMedian() {
if(smallheap.size()>bigheap.size()) return smallheap.top();
return 1.0*(smallheap.top()+bigheap.top())/2;
}

Welcome to my other publishing channels