面试题41:数据流中的中位数
题目:如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。
数据结构 | 插入的时间复杂度 | 得到中位数的时间复杂度 |
---|---|---|
没有排序的数组 | O(1) | O(n) |
排序的数组 | O(n) | O(1) |
排序的链表 | O(n) | O(1) |
二叉搜索树 | 平均 O(logn),最差O(n) | 平均O(logn),最差O(n) |
AVL树 | O(logn) | O(1) |
最大堆和最小堆 | O(logn) | O(1) |
// 利用大顶堆和小顶堆实现
#include<iostream>
#include<algorithm>
#include<set>
#include<vector>
using namespace std;
template<typename T> class DynamicArray{
public:
void Insert(T num){
if(((min.size()+max.size())&1)==0){ // 数据总数为偶数时
if(max.size()>0 && num<max[0]){ // 小于大顶堆的最大值, 放入大顶堆
max.push_back(num);
push_heap(max.begin(), max.end(), less<T>()); // less大顶堆 (默认)
num=max[0];
pop_heap(max.begin(), max.end(), less<T>());
max.pop_back();
}
min.push_back(num);
push_heap(min.begin(), min.end(), greater<T>()); // greater小顶堆
}else{
if(min.size()>0 && min[0]<num){
min.push_back(num);
push_heap(min.begin(), min.end(), greater<T>());
num=min[0];
pop_heap(min.begin(), min.end(), greater<T>());
min.pop_back();
}
max.push_back(num);
push_heap(max.begin(), max.end(), less<T>());
}
}
T GetMedian(){
int size=min.size()+max.size();
if(size==0) throw exception();
T median=0;
if((size&1)==1) median=min[0];
else median=(min[0]+max[0])/2;
return median;
}
private:
vector<T> min; // 小根堆
vector<T> max; // 大根堆
};
int main() {
DynamicArray<int> numbers;
numbers.Insert(5);
numbers.Insert(3);
numbers.Insert(4);
printf("%d", numbers.GetMedian());
return 0;
}