• 剑指offer系列——63.数据流中的中位数


    Q:如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。我们使用Insert()方法读取数据流,使用GetMedian()方法获取当前读取数据的中位数。
    T:
    1.最简单的方法,sort解决

    private:
        vector<int> numbers;
    public:
        void Insert(int num) {
            numbers.push_back(num);
        }
    
        double GetMedian() {
            sort(numbers.begin(), numbers.end());
            int length = numbers.size();
            int mid = length / 2;
            if (length % 2 == 0) {
                auto num1 = (double) numbers[mid - 1];
                auto num2 = (double) numbers[mid];
                return (num1 + num2) / 2;
            } else
                return (double) numbers[mid];
        }
    

    2.用AVL的实在……抗不动啊抗不动,我还是遇到AVL再去扛吧。
    3.大顶堆+小顶堆
    简单点,直接用priority_queue,方便又快捷(感谢@马客(Mark))

        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();
        }
    

    或者用堆(感谢@忆水寒)

    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];
            }
    
  • 相关阅读:
    ie浏览器下载附件中文乱码
    js 获取字符串中某字符第二次出现的下标
    uploadify附件上传 传参
    hibernate hql语句 注意事项
    违反检查约束条件
    xml中的<if>和截取字符串
    引用不了XXservice,怎么办?
    enctype="multipart/form-data"的form传参
    freemarker 嵌套循环 (导出word时,修改ftl模板)
    springboot 打包问题 项目依赖三方jar ,之前的同事是直接丢到项目lib下 ,今天使用springbioot打包的时候,找不到这个jar
  • 原文地址:https://www.cnblogs.com/xym4869/p/12378615.html
Copyright © 2020-2023  润新知