• 数据流中的中位数


    题目描述

    如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。
     
    思路:
    /*
    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();
        }
    
    };
    

      

    拥抱明天! 不给自己做枷锁去限制自己。 别让时代的悲哀,成为你人生的悲哀。
  • 相关阅读:
    SpringMVC 返回 json 字符串中文乱码
    两个HTML页面之间传值
    NOIP2018 保卫王国
    Arch Linux使用cisco anyconnect
    CSP模拟赛 巨神兵
    计蒜客The Fake Fake Friends
    Manjaro安装,配置,美化指南
    [国家集训队] Crash 的文明世界
    ZJOI2011 营救皮卡丘
    CF1198E Rectangle Painting 2
  • 原文地址:https://www.cnblogs.com/dd2hm/p/7488486.html
Copyright © 2020-2023  润新知