美文网首页数据结构&算法&人工智能
剑指offer编程题—数据流中的中位数

剑指offer编程题—数据流中的中位数

作者: 零岁的我 | 来源:发表于2020-03-14 12:54 被阅读0次

    题目描述
    如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。我们使用Insert()方法读取数据流,使用GetMedian()方法获取当前读取数据的中位数。

    解题思路
    如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。
    由于数据是动态插入的,显然不能等所有数据输入结束后进行统一排序。
    思路1

    1. 维护一个大顶堆和一个小顶堆,并保证如下两个特性:
      1)大顶堆中的所有记录均小于小顶堆中的记录:
      只要保证大顶堆顶元素始终小于小顶堆堆顶元素即可;
      2)大顶堆中总记录数量较小顶堆中的总记录数量,要么大1,要么相等:
      当大顶堆记录总数量较小顶堆中的总记录数量大于2时,取出大顶堆的堆顶元素插入小顶堆,此时两个堆中总记录数量相等;
      当大顶堆记录总数量较小顶堆中的总记录数量小1时,取出小顶堆的堆顶元素插入大顶堆,此时大顶堆记录总数量较小顶堆中的总记录数量大1;
    2. 如果从数据流中读出奇数个数值,那么中位数就是大顶堆的堆顶元素;如果从数据流中读出偶数个数值,那么中位数就是大顶堆的堆顶元素与小顶堆的堆顶元素的平均值;

    实现手段:C++容器适配器priority_queue<>是一种优先级队列,其排序规则是使用堆排序技术实现的。priority_queue<int,vector<int>,less<int> > 队列中元素并非完全有序,但能保证最大元素总在队头;priority_queue<int,vector<int>,greater<int> >队列原理相同,能保证最小元素总在队头。

    class Solution {
    public:
        priority_queue<int,vector<int>,less<int> > p; //p中记录按非递增排序,队头值最大
        priority_queue<int,vector<int>,greater<int> > q; //q中记录按非递减排序,队头值最小
        void Insert(int num)
        {
            if(p.empty() || num<=p.top()) p.push(num); //p中维持一个大顶堆,队头元素始终最大
            else q.push(num);
            //输入数据序列总个数为偶数时,保证队列p中记录个数与队列q中记录个数相等
            //输入数据序列总个数为奇数时,保证队列p中记录个数比队列q中记录个数多1
            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();
        }
    
    };
    

    相关文章

      网友评论

        本文标题:剑指offer编程题—数据流中的中位数

        本文链接:https://www.haomeiwen.com/subject/dhlvshtx.html