优先级队列:295. 数据流的中位数

在这里插入图片描述

个人主页 : 个人主页
个人专栏 : 《数据结构》 《C语言》《C++》《Linux》


前言

本题是我对写题的思路总结


295.数据流的中位数

一、题目解析

在这里插入图片描述
易知,本题是通过实现一个MedianFinder 类,来解决有序数组的中位数问题。

二、解题思路

1. 暴力求解

我们非常容易想到,用vector数组存储数据,在每次调用addNum函数时,先加入数组中,再对数组排序。那求解有序数组的中位数,只要判断数组元素数量是奇数还是偶数,就可以求出中位数了。但这样addNum函数的时间复杂度就是 O( nlog^n)。

在这里插入图片描述

2. 插入排序

该思路与暴力求解类似,只不过把sort排序,换成插入排序。我们同样使用vector num数组存储数据,只不过每次调用addNum函数时,我们直接从数组尾部向数组头部遍历数组,当遍历到一个数组元素小于要插入元素时,将元素插入该位置。这样addnum函数的时间复杂度为O(n)。

在这里插入图片描述

3. 大小堆求解

该方法我们将有序数组分为两个堆,其中前一部分为大堆,后一部分为小堆。
在这里插入图片描述

那么此时,我们易知,当left.size() == right.size()时,中位数mid = ( left.top() + right.top() ) / 2.0;当left.size() == right.size() + 1时,中位数mid = left.top()。
因为此时left.top() 不就是前一部分的最后一个元素,right.top()不就是后一部分的第一个元素。
那么如果我们要使上面方法成立,那我们必须满足 m == n || m == n + 1;
那么此时,对于调用addNum函数,我们有一个问题,那就是对于该插入的元素,我们要插入到 left 还是 right?

我们先定义如下变量:
在这里插入图片描述

我们分为两个情况考虑,a. m == n 。 b. m == n + 1。
在这里插入图片描述

  • 上述成立与否,是为了满足上面求中位值的方法。
  • 通过比较 x 与 val 的大小关系,来判断插入位置,是因为 x 是前一部分的最大值,如果 x < val 就表示 val 是属于 x 的右边部分(在有序数组中的位置)
    在这里插入图片描述
    此时我们就可以使用大小堆来求解中位数的问题了。

三、代码实现

使用大小堆的思路求解

class MedianFinder {
public:
    MedianFinder() {}
    
    void addNum(int num) {
        int m = left.size(), n = right.size();
        if(m == n)
        {
            if(left.size() == 0 || left.top() >= num)
            {
                left.push(num);
            }    
            else if(left.top() < num)
            {
                right.push(num);
                left.push(right.top());
                right.pop();
            }
        }
        else if(m == (n + 1))
        {
            if(num <= left.top())
            {
                left.push(num);
                right.push(left.top());
                left.pop();
            }
            else if(num > left.top())
            {
                right.push(num);
            }
        }
    }
    
    double findMedian() {
        int m = left.size(), n = right.size();
        if(m == n)
            return (left.top() + right.top()) / 2.0;

        return left.top() * 1.0; 
    }
private:
    priority_queue<int, vector<int>, less<int>> left;
    priority_queue<int, vector<int>, greater<int>> right;
};

总结

以上就是我对于如何使用优先级队列来处理数据流的中位数。

在这里插入图片描述

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

水月梦镜花

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值