题目描述:
如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。
例如,
[2,3,4] 的中位数是 3
[2,3] 的中位数是 (2 + 3) / 2 = 2.5
设计一个支持以下两种操作的数据结构:
void addNum(int num) - 从数据流中添加一个整数到数据结构中。
double findMedian() - 返回目前所有元素的中位数。
解题思路:
利用优先队列,一个优先队列Minqueue记录前半部分,队头应为队列最大值;一个优先队列Maxqueue记录后半部分,队头应为队列最小值。当添加num到数据结构中时:
①累计添加数为0时,将num添加到Minqueue中。
②num<=Minqueue队头元素时,即此时添加元素小于或等于中位数,则将其添加到Minqueue中,若此时Maxqueue.size()+1<Minqueue.size(),则将Minqueue队头元素添加到Maxqueue队列中。
③num>Minqueue队头元素时,即此时添加元素大于中位数,则将其添加到Maxqueue中,若此时Maxqueue.size()>Minqueue.size(),则将Maxqueue队头元素添加到Minqueue队列中。
综上所述,可知,当数据流有奇数个元素时,中位数为Minqueue队头元素,当数据流有偶数个元素时,中位数为Minqueue和Maxqueue队头元素的平均数。
过程图解:
代码部分:
class MedianFinder {
public:
/** initialize your data structure here. */
priority_queue<int,vector<int>,less<int>> Minqueue;
priority_queue<int,vector<int>,greater<int>> Maxqueue;
MedianFinder() {
}
void addNum(int num) {
if(Minqueue.empty() || num<=Minqueue.top())
{
Minqueue.push(num);
if(Maxqueue.size()+1<Minqueue.size())
{
Maxqueue.push(Minqueue.top());
Minqueue.pop();
}
}else{
Maxqueue.push(num);
if(Maxqueue.size()>Minqueue.size())
{
Minqueue.push(Maxqueue.top());
Maxqueue.pop();
}
}
}
double findMedian() {
if(Minqueue.size()>Maxqueue.size())
return Minqueue.top();
else return (Minqueue.top()+Maxqueue.top())/2.0;
}
};
/**
* Your MedianFinder object will be instantiated and called as such:
* MedianFinder* obj = new MedianFinder();
* obj->addNum(num);
* double param_2 = obj->findMedian();
*/