LeetCode——295. Find Median from Data Stream

Stella981
• 阅读 531

一.题目链接:

  https://leetcode.com/problems/find-median-from-data-stream

二.题目大意:

  给定一段数据流,要求求出数据流中的中位数,其中数据流是动态变化的。如果数据流中的数字个数是奇数的话,则中位数是中间位置的数字;如果数据流中的数字是偶数的话,则中位数是排序好的数据流中的中间两个数的的平均值。

三.题解:

  如果数据流是静态不变的话,此时问题是比较好求解的。但是数据流是动态变化的,所以数据流中每次进入一个新的数字时,都要保证能够高效的找到数据流的中位数。我们可以这么考虑:如果把数据流中的数字分为个数相同的两部分的话(假设为A和B,其中A中的数字全部小于B中的数字),那么我们所求的中位数,实质就是A中的最大值和B中的最小值的平均值。因此,我们可以用两个堆来表示这个过程,其中大顶堆maxH存储的是数据流中的数值较小的数字,而小顶堆minH存储的是数据六中数值较大的数字,且maxH中的数字全部小于minH中的数字。并且堆可以快速的找出其中的最值,所以可以快速找得到minH中的最小值和maxH中的最大值,从而求出中位数。代码如下:

#include<iostream>
#include<unordered_map>
#include<queue>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<sstream>
#include<set>
#include<map>
#include<stack>
#define MAX_NUM 100
using namespace std;
class MedianFinder {
public:
    /** initialize your data structure here. */
    priority_queue<int,vector<int>,less<int>> maxH;//定义大顶堆,用于存储较小的数据部分
    priority_queue<int,vector<int>,greater<int>> minH;//定义小顶堆,用于存储较大的数据部分
    MedianFinder() {

    }

    void addNum(int num) {
        maxH.push(num);
        int tmp = maxH.top();
        maxH.pop();
        minH.push(tmp);//保证小顶堆中的数据大于大顶堆中的数据
        if(minH.size() > maxH.size())
        {
            int tmp = minH.top();
            minH.pop();
            maxH.push(tmp);//保证大顶堆中的数据小于小顶堆中的数据
        }

    }

    double findMedian() {
        if(minH.size() == maxH.size())//如果两个堆的大小相同,则返回它们最值的平均值
            return (minH.top() + maxH.top()) / 2.0;
        return minH.size() > maxH.size() ? minH.top() : maxH.top();//如果两个堆的大小不相同,返回数字个数多的堆的最值
    }
};

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


int main()
{
    MedianFinder test = MedianFinder();
    test.addNum(1);
    test.addNum(2);
    test.addNum(3);
    test.addNum(4);
    test.addNum(5);
    cout<<test.findMedian()<<endl;


}

每次从数据流中找出中位数的时间为O(1),调整两个堆的时间为O(logN),对于含有n个数字的数据流,总的时间复杂度为O(NlogN),空间复杂度为O(N)。

此外,有几个点需要注意下:

1.代码中使用了priority_queue即优先队列来实现堆,因为优先队列获取优先级最高的值所需时间为O(1),调整的过程为O(logN),与堆的操作时间类似,能较好的模拟堆。

2.通常情况下,堆默认的优先级最高的值是指的最大值,也可以是最小值,不过需要显式的说明(见本例中优先队列的定义)。

3.要保证最小堆中存储的始终是较大的数值,而大顶堆中存储的是较小的数值。所以才会有addNum中的那些操作。

点赞
收藏
评论区
推荐文章
Stella981 Stella981
2年前
LeetCode 58. 最后一个单词的长度 (java)
题目:https://leetcodecn.com/problems/lengthoflastword/submissions/(https://www.oschina.net/action/GoToLink?urlhttps%3A%2F%2Fleetcodecn.com%2Fproblems%2Flengthoflastw
Stella981 Stella981
2年前
LeetCode 169. 求众数
原文链接: LeetCode169.求众数(https://my.oschina.net/ahaoboy/blog/3118038)https://leetcodecn.com/problems/majorityelement/(https://www.oschina.net/action/GoToLink?urlhttps%3A%2F
Stella981 Stella981
2年前
LeetCode 72. 编辑距离
原文链接: LeetCode72.编辑距离(https://my.oschina.net/ahaoboy/blog/3113850)https://leetcodecn.com/problems/editdistance/(https://www.oschina.net/action/GoToLink?urlhttps%3A%2F%2F
Stella981 Stella981
2年前
Search Insert Position
\toc\题目链接SearchInsertPositionLeetCode(https://www.oschina.net/action/GoToLink?urlhttps%3A%2F%2Fleetcode.com%2Fproblems%2Fsearchinsertposition%2F)注意点
Stella981 Stella981
2年前
Leetcode 239题 滑动窗口最大值(Sliding Window Maximum) Java语言求解
题目链接https://leetcodecn.com/problems/slidingwindowmaximum/(https://www.oschina.net/action/GoToLink?urlhttps%3A%2F%2Fleetcodecn.com%2Fproblems%2Fslidingwindowmaximum%
Stella981 Stella981
2年前
LeetCode 1192. Critical Connections in a Network
原题链接在这里:https://leetcode.com/problems/criticalconnectionsinanetwork/(https://www.oschina.net/action/GoToLink?urlhttps%3A%2F%2Fleetcode.com%2Fproblems%2Fcriticalconnections
Stella981 Stella981
2年前
LeetCode 39. Combination Sum
问题链接LeetCode39.CombinationSum(https://www.oschina.net/action/GoToLink?urlhttps%3A%2F%2Fleetcode.com%2Fproblems%2Fcombinationsum%2Fdescription%2F)题目解析给一组数和一个目
Stella981 Stella981
2年前
LeetCode 0078. Subsets子集【Python】
LeetCode0078.Subsets子集【Medium】【Python】【回溯】ProblemLeetCode(https://www.oschina.net/action/GoToLink?urlhttps%3A%2F%2Fleetcode.com%2Fproblems%2Fsubsets%2F)Givenaset
Stella981 Stella981
2年前
851. Loud and Rich —— weekly contest 87
851\.LoudandRich题目链接:https://leetcode.com/problems/loudandrich/description/(https://www.oschina.net/action/GoToLink?urlhttps%3A%2F%2Fleetcode.com%2Fpr
Stella981 Stella981
2年前
925. Long Pressed Name
题目链接:https://leetcode.com/problems/longpressedname/description/(https://www.oschina.net/action/GoToLink?urlhttps%3A%2F%2Fleetcode.com%2Fproblems%2Flongpressedname%2Fdescript