数据流中的中位数

题目

  如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。

思路

  使容器左边的数都小于右边的数,即使左右两边的数没有排序,也能根据左边最大的数和右边最小的数来实现查中位数。所以左边用大顶锥实现,右边用小顶锥实现。只需要O(1)的时间就可以实现的到顶锥的数据。

  如果数据总数目是偶数,插入小顶锥,否则插入大顶锥。要保证大顶锥中的数字都小于小顶锥中的数字,如果是偶数时,插入小顶锥,如果此时的数据比小顶锥中的数据小,怎么办?

  解决:

    插入小顶锥时,先把数据插入大顶锥,接着把大顶锥中最大数字拿出来插入小顶锥,最终插入的数字就是原大顶锥中最大的数字,这样就保证了小顶锥中的数字都比大顶锥中的数字大。

    插入大顶锥与插入小顶锥类似...

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

template <typename T>
class Solution
{
    public:
        void insert(T &num);
        T get_num();
    private:
        vector<T> min;//右边最小堆--第一个数字最小 
        vector<T> max;//左边最大堆---第一个数字最大 
};
template <typename T>
void Solution<T>::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>());//升序 
            
            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>());//降序 
    }
    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>());
    }    
}
template<typename T>
T Solution<T>::get_num()
{
    int size=max.size()+min.size();
    if(!size)
    {
        cerr<<"no number available"<<endl;
        return 0x3f3f;
    }
    int mid=0;
    if(size&1)
        return min[0];
    else
        return (min[0]+max[0])/2;
}
int main()
{
    vector<int> v{1,4,9,7,5,6};
    Solution<int> s;
    for(int i=0;i<v.size();++i)
    {
        s.insert(v[i]);
    }
    if(s.get_num()!=0x3f3f)
        cout<<s.get_num()<<endl;
    else
    {
        cerr<<"数组有误."<<endl;
        return 0;
    }
    return 0;
}

 code

class Solution {
public:
    void Insert(int num)
    {
        if(max.empty()||num<=max.top())
            max.push(num);
        else
            min.push(num);
        //左边的大顶锥最多比右边的小顶锥的容量大一(奇数)
        if(max.size()==min.size()+2)
        {
            min.push(max.top());
            max.pop();
        }
        //最后返回的是左边的大顶锥锥顶,所以右边的小顶锥不能比左边的大顶锥容量大
        if(max.size()+1==min.size())
        {
            max.push(min.top());
            min.pop();
        }
        return ;
    }

    double GetMedian()
    { 
        return max.size()==min.size()?(max.top()+min.top())/2.0:max.top();
    }
private:
    priority_queue<int,vector<int>,less<int>> max;
    priority_queue<int,vector<int>,greater<int>> min;
};

 

posted on 2019-01-07 23:29  tianzeng  阅读(953)  评论(0编辑  收藏  举报

导航