ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

[题解]剑指 Offer 41. 数据流中的中位数(C++)

2021-08-27 18:34:42  阅读:208  来源: 互联网

标签:Offer 题解 addNum C++ 中位数 large small findMedian MedianFinder


题目

如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。

例如,

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

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

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

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

输入:
["MedianFinder","addNum","addNum","findMedian","addNum","findMedian"]
[[],[1],[2],[],[3],[]]
输出:[null,null,null,1.50000,null,2.00000]

示例 2:

输入:
["MedianFinder","addNum","findMedian","addNum","findMedian"]
[[],[2],[],[3],[]]
输出:[null,null,2.00000,null,2.50000]

限制:

  • 最多会对 addNum、findMedian 进行 50000 次调用。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/shu-ju-liu-zhong-de-zhong-wei-shu-lcof
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路

这题考察的就是使用什么样的数据结构来存数据流的数并且排序。如果使用vector,那么每次插入新数排序都很麻烦,虽然利用二分查找确认要插入的位置只需要时间复杂度O(log(n)),但是需要将插入位置之后的元素全部往后移动;利用有序数据结构,我想到的是优先队列(堆),即STL中的priority_queue,关于priority_queue具体说明可以参考这里:https://en.cppreference.com/w/cpp/container/priority_queue
只用一个优先队列虽然可以解决插入数据的问题,但是要查找中位数却很麻烦,难道每次查找要pop掉一半的数据出来再插回去?解决方案也很简单:用两个优先队列。一个是大根堆,一个是小根堆,保证大根堆堆顶元素比小根堆堆顶元素还要小,同时两个堆的元素数量一样或者只相差1,如果它们数量一样,那么中位数就是两个堆堆顶元素的均值;如果不一样,那就是多1个的那个堆的堆顶元素。为了方便,可以在插入数据时设计保持其中一个堆的元素数量不少于另一个堆。
每次添加新元素的时间复杂度是O(n),查询中位数的时间复杂度则是O(1),空间复杂度O(n)。

代码

class MedianFinder {
public:
    /** initialize your data structure here. */
    MedianFinder() {

    }
    
    void addNum(int num) {
        small.push(num);
        large.push(small.top());
        small.pop();
        if(large.size() > small.size())
        {
            small.push(large.top());
            large.pop();
        }
    }
    
    double findMedian() {
        return small.size() > large.size() ? small.top() : (small.top() + large.top())/2.0;
    }

private:
    priority_queue<int, vector<int>, less<int>> small;
    priority_queue<int, vector<int>, greater<int>> large;
};

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

标签:Offer,题解,addNum,C++,中位数,large,small,findMedian,MedianFinder
来源: https://www.cnblogs.com/fusheng-chana/p/15194898.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有