题目链接
求动态数组的中位数,我们可以用两个堆来求.(这个是很经典的面试题)
思想:分为两个堆 大顶堆对应有序序列的left(数据较小)部分 小顶堆对应有序序列的right(数据较大)部分
根据只需获得中间数的想法,可以将数据分为左右两边,一边以最大堆的形式实现,可以快速获得左侧最大数, 另一边则以最小堆的形式实现。
同时,要保证两个堆的数据长度相差不能过大.
代码如下:
class MedianFinder {
public:
/** initialize your data structure here. */
//分为两个堆 大顶堆对应有序序列的left部分 小顶堆对应有序序列的right部分
priority_queue<int,vector<int>,less<> > left;//大顶堆
priority_queue<int,vector<int>,greater<> > right;//小顶堆
MedianFinder() {
}
void addNum(int num) {
if(left.size()==0&&right.size()==0){
left.push(num);//刚开始如果都为空,那么先放入大顶堆left
return ;
}
if(num>left.top()) right.push(num);//以大顶堆top为基准,如果大于left.top(),则放入right
else left.push(num);//反之,放入left
if(right.size()>left.size()+1){//再考虑两个堆的数据长度 如果长度相差大于2 push pop
left.push(right.top());
right.pop();
} else if(left.size()>right.size()+1){
right.push(left.top());
left.pop();
}
}
double findMedian() {
if(left.size()==right.size()) return (left.top()+right.top())/2.0;//如果两个堆的长度相同 说明是偶数,求两个top的平均数
else return left.size()>right.size()?left.top():right.top();//否则,为奇数,谁的数据长度大,则返回谁的top()
}
};
/**
* Your MedianFinder object will be instantiated and called as such:
* MedianFinder* obj = new MedianFinder();
* obj->addNum(num);
* double param_2 = obj->findMedian();
*/