题目描述

如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。
 
思路:
/*
C++ 最大堆 最小堆 实现
用大顶堆实现左边的的数据容器,小顶堆实现右边的数据容器。往堆中插入一个数据时间复杂度O(logn),而得到最大值(或最小值)只需O(1)时间。有一点需要注意,我们要保证数据被平均分配到两个堆中(想想为什么?),因此两堆大小之差不能超过1。实现方法是数据流中奇数位的数插入小顶堆中,偶数位的数插入大顶堆中。同时还要保证大顶堆中的所有数都要小于小顶堆中的数。考虑一种特殊情况,例如,插入偶数位的数,按照分配规则应该插入大顶堆中,但是这个数大于小顶堆的最小值怎么办?如果直接插入大顶堆,就不符合大顶堆所有值都小于小顶堆的值这一条件。可以这样解决:想把该数插入小顶堆,然后进行堆排序,接着讲小顶堆的最小值拿出来插入到大顶堆中,这样就满足所有条件了。同理插入奇数位的数时也要考虑这种特殊情况。
*/
class Solution {
   
private:
        vector<int> min;
        vector<int> max;
public:
        void Insert(int num)
        {
           if(((min.size()+max.size())&1)==0)//偶数时 ,放入最小堆
           {
              if(max.size()>0 && num<max[0])
              {
                // push_heap (_First, _Last),要先在容器中加入数据,再调用push_heap ()
                 max.push_back(num);//先将元素压入容器
                 push_heap(max.begin(),max.end(),less<int>());//调整最大堆
                 num=max[0];//取出最大堆的最大值
                 //pop_heap(_First, _Last),要先调用pop_heap()再在容器中删除数据
                 pop_heap(max.begin(),max.end(),less<int>());//删除最大堆的最大值
                 max.pop_back(); //在容器中删除
              }
              min.push_back(num);//压入最小堆
              push_heap(min.begin(),min.end(),greater<int>());//调整最小堆
           }
           else//奇数时候,放入最大堆
           {
              if(min.size()>0 && num>min[0])
              {
                // push_heap (_First, _Last),要先在容器中加入数据,再调用push_heap ()
                 min.push_back(num);//先压入最小堆
                 push_heap(min.begin(),min.end(),greater<int>());//调整最小堆
                 num=min[0];//得到最小堆的最小值(堆顶)
                 //pop_heap(_First, _Last),要先调用pop_heap()再在容器中删除数据
                 pop_heap(min.begin(),min.end(),greater<int>());//删除最小堆的最大值
                 min.pop_back(); //在容器中删除
              }
              max.push_back(num);//压入数字
              push_heap(max.begin(),max.end(),less<int>());//调整最大堆
           }   
        }
        /*获取中位数*/      
        double GetMedian()
        {
            int size=min.size()+max.size();
            if(size<=0) //没有元素,抛出异常
                return 0;//throw exception("No numbers are available");
            if((size&1)==0)//偶数时,去平均
                return ((double)(max[0]+min[0])/2);
            else//奇数,去最小堆,因为最小堆数据保持和最大堆一样多,或者比最大堆多1个
                return min[0];
        }

};

  

 
 
 
大神“马客”的代码看不懂~~~~
//设置左右两个堆
//1.保证左边的堆<=右边的堆
//2.保证两个堆大小之差能取到中位数
class Solution {
    priority_queue<int, vector<int>,less<int> >p;
    priority_queue<int, vector<int>,greater<int> >q;
    
public:
    void Insert(int num)
    {
        if(p.empty() || num<=p.top()) p.push(num);
        else q.push(num);
        if(p.size()== q.size()+2)	q.push(p.top()),p.pop();
    	if(p.size()+1==q.size())    p.push(q.top()),q.pop();
    }

    double GetMedian()
    { 
    	return p.size()==q.size()?(p.top()+q.top())/2.0 : p.top();
    }

};

  

posted on 2017-09-07 10:40  王小东大将军  阅读(242)  评论(0编辑  收藏  举报