Leedcode 刷题:295. 数据流的中位数 2020年6月15日--堆、树

295. 数据流的中位数

中位数是有序列表中间的数。如果列表长度是偶数,中位数则是中间两个数的平均值。
例如,

[2,3,4] 的中位数是 3

[2,3] 的中位数是 (2 + 3) / 2 = 2.5

设计一个支持以下两种操作的数据结构:

void addNum(int num) - 从数据流中添加一个整数到数据结构中。
double findMedian() - 返回目前所有元素的中位数。

示例:

addNum(1)
addNum(2)
findMedian() -> 1.5
addNum(3) 
findMedian() -> 2

进阶:

如果数据流中所有整数都在 0 到 100 范围内,你将如何优化你的算法?
如果数据流中 99% 的整数都在 0 到 100 范围内,你将如何优化你的算法?

tag:优先队列、双堆、排序、二叉搜索树
思考:菜鸡的我第一时间想到的是无脑的暴力解决,在查询的时候排序,这样显然复杂度太大,数据流是不断动态调整的这种方法结果就是超时。以下是官方的用法(ps:位运算符的用法,又给我上了一课,看过和理解是两回事。能运用才算真正学会)

class MedianFinder {
    vector<double> store;

publicvoid addNum(int num)
    {
        store.push_back(num);
    }
    double findMedian()
    {
        sort(store.begin(), store.end());

        int n = store.size();
        //n与1位运算,一个数 & 1的结果就是取二进制的最末位。这可以用来判断一个整数的奇偶
        return (n & 1 ? store[n / 2] : (store[n / 2 - 1] + store[n / 2]) * 0.5);
    }

另一种方法就是使用二分查找low_bound实现插入排序,思路大致相同但查询放在了添加阶段。

双堆法

这是一种比较容易想到的双堆比较,逻辑比较简单,第一个元素先推入大顶堆,此后,依照大小,分别推入大小顶堆,当两侧失衡时,切换对顶且退栈一元素。查找中位数时也是使用的比较笨的直观的办法。

class MedianFinder {
    priority_queue<double> big_queue;                              // max heap
    priority_queue<double, vector<double>, greater<double>> small_queue;   // min heap

public:
    // Adds a number into the data structure.
    void addNum(int num)
    {
        if (big_queue.empty()){
            big_queue.push(num);
            return;
        }
        if (big_queue.size() == small_queue.size()){
            if (num<big_queue.top()){
                big_queue.push(num);
            }
            else{
                small_queue.push(num);
            }
        }
        else if(big_queue.size() > small_queue.size()){
            if(num>big_queue.top()){
                small_queue.push(num);
            }
            else{
                small_queue.push(big_queue.top());
                big_queue.pop();
                big_queue.push(num);
            }
        }
        else if(big_queue.size() < small_queue.size()){
            if(num<small_queue.top()){
                big_queue.push(num);
            }
            else{
                big_queue.push(small_queue.top());
                small_queue.pop();
                small_queue.push(num);
            }
        }
    }

    // Returns the median of current data stream
    double findMedian()
    {
        if(big_queue.size() == small_queue.size()){
            return (big_queue.top() + small_queue.top())/2;
        }
        else if( big_queue.size() > small_queue.size()){
            return big_queue.top();
        }
        return small_queue.top();
    }
};

/**
 * Your MedianFinder object will be instantiated and called as such:
 * MedianFinder* obj = new MedianFinder();
 * obj->addNum(num);
 * double param_2 = obj->findMedian();
 */

leetcode 大佬更简洁版本,采用的方法是
两个优先级队列:
用于存储较小一半数字的最大堆 lo
用于存储较大一半数字的最小堆 hi
元素输入后不需要判断元素的大小,而是直接插入储存较小一半数字的大顶堆,大顶堆自动修正后,如果大顶堆大小小于小顶堆此时将它的堆顶删除并插入到小顶堆,这样我们可以保证堆的平衡。

class MedianFinder {
    priority_queue<int> lo;                              // max heap
    priority_queue<int, vector<int>, greater<int>> hi;   // min heap

public:
    // Adds a number into the data structure.
    void addNum(int num)
    {
        lo.push(num);                                    // Add to max heap

        hi.push(lo.top());                               // balancing step
        lo.pop();

        if (lo.size() < hi.size()) {                     // maintain size property
            lo.push(hi.top());
            hi.pop();
        }
    }

    // Returns the median of current data stream
    double findMedian()
    {
        return lo.size() > hi.size() ? (double) lo.top() : (lo.top() + hi.top()) * 0.5;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值