Median is the middle value in an ordered integer list. If the size of the list is even, there is no middle value. So the median is the mean of the two middle value.
Examples: [2,3,4]
, the median is 3
[2,3]
, the median is (2 + 3) / 2 = 2.5
Design a data structure that supports the following two operations:
- void addNum(int num) - Add a integer number from the data stream to the data structure.
- double findMedian() - Return the median of all elements so far.
For example:
add(1) add(2) findMedian() -> 1.5 add(3) findMedian() -> 2题意:设计一种数据结构能快速的返回输入的数据流的中间值(排好序时的最中间的值)。
思路1.:用一个双向队列存储,然后每插入一个数,就进行插入排序,查询是直接返回中间下标值。这样的话插入的时间复杂度是O(n), 得到的结果是超时。
思路2:用一个最大堆,一个最小堆来记录数据,假想这是已经有序的数据,则从中间截开,大的一半存最小堆里,这样堆顶的元素是有序时靠近中间的那个值;小的一半存最大堆里,这样堆顶的元素也是靠近中间的那个;然后继续来数据num,如果num大于中间的值,则把num加入右边的堆中(最小堆),这时候看一下堆里的元素个数,如果多于前半段元素的个数,就把堆顶的元素除去,加入前一半的堆里;如果num在前半段,则把num加入前半段的堆里,然后检测前半段的元素个数,是否比后半段的元素多的大于1,如果多的大于1,就把前半段的堆顶拿去,放在后半段的元素里,即始终维持前半段堆的元素个数等于后半段堆的元素个数,或者比后半段堆的元素个数大1。这样查询时,如果前半段堆元素数多1,则直接返回前半段堆的堆顶元素;如果前后半段堆的元素个数相等,则返回两个堆顶的元素和处以2.
class MedianFinder {
public:
// Adds a number into the data structure.
void addNum(int num) {
if (maxque.empty() && minque.empty()){
maxque.push(num);
return;
}
if (num > maxque.top()){
minque.push(num);
if (minque.size() > maxque.size()){
int tmp = minque.top();
minque.pop();
maxque.push(tmp);
}
}
else{
maxque.push(num);
if (maxque.size() - minque.size() > 1){
int tmp = maxque.top();
maxque.pop();
minque.push(tmp);
}
}
}
// Returns the median of current data stream
double findMedian() {
if (maxque.size() > minque.size()){
return maxque.top();
}
else{
return (maxque.top() + minque.top()) / 2.0;
}
}
private:
priority_queue<int, vector<int>, less<int>> maxque;
priority_queue<int, vector<int>, greater<int>> minque;
};
// Your MedianFinder object will be instantiated and called as such:
// MedianFinder mf;
// mf.addNum(1);
// mf.findMedian();