#剑指offer63数据流中的中位数

数据流中的中位数

https://www.nowcoder.com/practice/9be0172896bd43948f8a32fb954e1be1?tpId=13&&tqId=11216&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking

剑指offer63数据流中的中位数

剑指offer63
牛客其他博客参考
图片说明
图片说明

题目分析:
数据流动态不断插入,找数据流中位数
1、暴力解法--不断排序
时间复杂度:Insert: O(1) GetMdeian: O( nlog(n) ) 空间复杂度:O(n)
个人代码

//暴力方法 --不断排序 取中
    vector<int>v;
    void Insert(int num) {
        v.push_back(num);
    }

    double GetMedian() { 
        sort(v.begin(),v.end());
        if((v.size()&1)==1)
        {
            return v[v.size()/2];
        }
        else
        {
            return (v[v.size()/2]+v[(v.size()-1)/2])/2.0;
        }
    }

2、插入排序
个人代码

class Solution {
public:
    //插入排序-- 因为数据流一个个进入,所以可以选择插入排序,每次插入一个元素,
    //要插入的序列是有序的,也就是说数据流插入n个数,时间只是进行了一次插入排序
    //实际:无论插入还是暴力都无意义,只要插入时放入合适位置(每次插入的思想遍历一遍),
    //      GetMedian中并不需要排序,时间复杂度一致,优化无意义
    vector<int>v;
    void Insert(int num) {
        if(v.empty())
            v.push_back(num);
        else //把元素插入合适位置,为了避免插入时需要移位,遍历两遍,用插入排序思想,从后往前遍历找位置
        {
            v.push_back(num);
            int i=v.size()-2;
            for(i=v.size()-2;i>=0;i--)
            {
                if(v[i]>num)
                {
                    v[i+1]=v[i]; //后移
                }
                else
                    break;
            }
            v[i+1]=num;
        }
    }

    double GetMedian() { 
        if((v.size()&1)==1)
            return 1.0*v[v.size()/2];
        else
            return (v[v.size()/2]+v[(v.size()-1)/2])/2.0;
    }

};

3、经典方法-- 大顶堆、小顶堆
[3]:https://www.nowcoder.com/profile/396966893/codeBookDetail?submissionId=110233652
[个人代码参考][3]
同时建立一个大顶堆(根节点最大),小顶堆(根节点最小),保持大顶堆小顶堆数据数量平衡,大顶堆放入数据较小值,小顶堆放入数据较大值,这样最后中位数取值完全由大顶堆和小顶堆的根节点值确定
数据流元素经过小顶堆筛选后(筛选出当前小顶堆最小值)插入大顶堆,每次插入都检查大顶堆小顶堆中元素数量是否平衡(差值超过1),不平衡则大顶堆的根节点弹出插入小顶堆,这样始终保持:1、大顶堆元素数量=大顶堆元素数量+1,或者大顶堆元素数量=大顶堆元素数量
2、大顶堆始终是所有数据中较小的一半元素,小顶堆始终是所有数据中较大的一半元素
时间复杂度:insert: O(logn) GetMdeian: O(1)
空间复杂度:insert: O(n) GetMdeian: O(1)
n个元素的数据流插入取中位数的实际复杂度 :O(nlogn) ,空间复杂度:O(n)
知识补充:priority_queue'

图片说明
自定义类型情况:
图片说明
转载链接

class Solution {
public:
    priority_queue<int>bigMap;//或者priority_queue<int,vector<int>,less<int>>bigMap;
    priority_queue<int,vector<int>,greater<int>>smallMap;//小顶堆,存放较大值
    void Insert(int num) {
        smallMap.push(num);
        bigMap.push(smallMap.top()); //经小顶堆筛选后,先插入大顶堆
        smallMap.pop();
        if((bigMap.size()-smallMap.size())>1) //检查是否平衡,不平衡调整
        {
            smallMap.push(bigMap.top());
            bigMap.pop();
        }
    }

    double GetMedian() { 
        double n1=static_cast<double>(bigMap.top()); //较小
        double n2=static_cast<double>(smallMap.top()); //较大值
        if(bigMap.size()==smallMap.size()) //偶数个元素
            return (n1+n2)/2.0;
        else
            return n1;
    }
};
全部评论

相关推荐

10-04 17:25
门头沟学院 Java
snqing:Java已经饱和了,根本不缺人。随便一个2000工资的都200人起投递
点赞 评论 收藏
分享
牛客101244697号:这个衣服和发型不去投偶像练习生?
点赞 评论 收藏
分享
评论
点赞
收藏
分享
牛客网
牛客企业服务