zoukankan      html  css  js  c++  java
  • 【剑指offer】数据流中的中位数

    题目描述

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

    分析:大根堆小根堆法

    现在假设数组有序,如果我们把数组的前半部分放入一个大根堆,数组的后半部分放入一个小根堆,那么中位数就只能是大根堆的堆顶元素和小根堆的堆顶元素,或者二者堆顶元素的平均值

    我们在插入的时候只有遵循某种规则,就能达到这种效果

    插入的时候两个堆的元素数量不同,则将新元素插入数量少的堆

    若元素数量相同,则随便插入一个堆

    若大根堆的堆顶元素大于小根堆的堆顶元素,则交换其堆顶元素

    插入完成后,根据元素的数量来确定中位数的值

    时间复杂度:插入一个数O(N*log N),获取中位数O(1)

    class Solution
    {
    public:
    
        priority_queue<int,vector<int>,less<int> > q1;    //大根堆
        priority_queue<int,vector<int>,greater<int> > q2; //小根堆
    
        //插入数
        void Insert(int um)
        {
            int x=um;
    
            //插入规则
            if(q1.size()==q2.size())
            {
                q2.push(x);
            }
            else if(q2.size()>q1.size())
            {
                q1.push(x);
            }
            else if(q1.size()>q2.size())
            {
                q2.push(x);
            }
    
            //根据大根堆小根堆堆顶元素的关系判断是否交换堆顶元素,
            //保证堆中的数据是正确的
            //(即大根堆保存有序数组前半部分的元素,小根堆保存有序数组后半部分的元素)
            if(q1.size()!=0&&q2.size()!=0)
            {
                if(q1.top()>q2.top())
                {
                    int a=q1.top();
                    int b=q2.top();
                    q1.pop();
                    q2.pop();
                    q1.push(b);
                    q2.push(a);
                }
            }
        }
        double GetMedian()
        {
            double x;
    
            //根据元素的数量奇偶和元素的分布来求中位数
            if(q1.size()==q2.size())
            {
                x=(q1.top()*1.0+q2.top()*1.0)/2.0;
            }
            else if(q2.size()>q1.size())
            {
                x=q2.top()*1.0;
            }
            else if(q1.size()>q2.size())
            {
                x=q1.top()*1.0;
            }
            return x;
        }
    };
  • 相关阅读:
    JSON
    类的操作
    轮播图
    定时器的应用
    延时调用
    定时器
    跳表的java实现,转载自网络,仅供自己学习使用
    java实现判断两个二叉树是否相同
    开发小白工作过程中的一些经验记录,仅供自己参看查阅,转载请注明出处
    安卓基础入门二,转载自网络
  • 原文地址:https://www.cnblogs.com/yinbiao/p/11596780.html
Copyright © 2011-2022 走看看