算法进阶——数据流中的中位数

题目


如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。我们使用Insert()方法读取数据流,使用GetMedian()方法获取当前读取数据的中位数。

数据范围:数据流中数个数满足 1≤n≤1000 ,大小满足 1≤val≤1000 。

进阶: 空间复杂度O(n), 时间复杂度O(nlogn)

示例1

复制代码
输入:
[5,2,3,4,1,6,7,0,8]
返回值:
"5.00 3.50 3.00 3.50 3.00 3.50 4.00 3.50 4.00 "
说明:
数据流里面不断吐出的是5,2,3...,则得到的平均数分别为5,(5+2)/2,3...   

示例2

复制代码
输入:
[1,1,1]
返回值:
"1.00 1.00 1.00 "

思路


本题是对顶堆算法的一个经典题,所谓对顶堆算法,实际上就是使用一个小顶堆和一个大顶堆(C++中的priority_queue)。

对于求动态中位数的问题,利用堆的性质,可以在O(nlogn)的时间复杂度取出最大值或最小值,那么我们可以用大顶堆维护前一半的数,用小顶堆维护后面一半的数。

规定若元素总数为奇数,那么大顶堆的元素个数要比小顶对的个数多1,这样,当总数为奇数时,中位数就是大顶堆的堆顶元素;当总数为偶数时,中位数就大顶堆堆顶和小顶堆堆顶元素的平均值。

具体做法是,在每次输入的时候将数字先加入大顶堆,大顶堆排序后,将大顶堆的最大值弹出加入小顶堆,小顶堆在进行排序。为了保持规定中的平衡,如果大顶堆的大小小于小顶堆,则需要弹出小顶堆的最大值加入大顶堆。

解答代码


cpp 复制代码
#include <queue>
class Solution {
public:
    priority_queue<int> max_top_heap; // 大顶堆,存较小的值
    priority_queue<int, vector<int>, greater<int>> min_top_heap; // 小顶堆,存较大的值

    void Insert(int num) {
        max_top_heap.push(num);
        min_top_heap.push(max_top_heap.top());
        max_top_heap.pop();

        if (max_top_heap.size() < min_top_heap.size()) {
            max_top_heap.push(min_top_heap.top());
            min_top_heap.pop();
        }
        
    }

    double GetMedian() { 
        int size = max_top_heap.size() + min_top_heap.size();
        if ((size&1) == 1) {
            // 奇数
            return static_cast<double>(max_top_heap.top());
        } else {
            // 偶数
            return static_cast<double>(
                (max_top_heap.top() + min_top_heap.top()) / 2.0);
        }
    }

};
相关推荐
IT古董1 小时前
【第五章:计算机视觉-项目实战之推荐/广告系统】2.粗排算法-(3)理解粗排模型之在线部分:在线架构及对双塔的应用
算法·1024程序员节
大数据张老师1 小时前
数据结构——平衡二叉树
数据结构·算法·查找
py有趣1 小时前
LeetCode算法学习之合并区间
学习·算法·leetcode
m0_748233641 小时前
单调栈详解【C/C++】
c语言·c++·算法·1024程序员节
郝学胜-神的一滴1 小时前
Linux中的`fork`函数详解:深入解析
linux·服务器·开发语言·c++·算法
大数据张老师2 小时前
数据结构——BF算法
数据结构·算法·1024程序员节
让我们一起加油好吗2 小时前
【数论】欧拉定理 && 扩展欧拉定理
c++·算法·数论·1024程序员节·欧拉定理·欧拉降幂·扩展欧拉定理
一匹电信狗3 小时前
【LeetCode_876_2.02】快慢指针在链表中的简单应用
c语言·数据结构·c++·算法·leetcode·链表·stl
胖咕噜的稞达鸭3 小时前
算法入门---专题二:滑动窗口2(最大连续1的个数,无重复字符的最长子串 )
c语言·数据结构·c++·算法·推荐算法·1024程序员节
兮山与3 小时前
算法18.0
算法