数据流中的中位数

题目描述

如何得到一个数据流中的中位数?

如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。

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

样例

Input:1, 2, 3, 4
Output:1,1.5,2,2.5
## 解释:每当数据流读入一个数据,就进行一次判断并输出当前的中位数。

解题思路

  • 描述

    我们定义一个count用于计数,一个val用于存储计数的数字。遍历数组,如果count为0,则将当前值赋值val,然后count++;如果count不为0,如果当前值等于val,则count++,否则count–。

    本题目同样是使用大顶堆和小顶堆。

    大顶堆和小顶堆的特点:每一次通过 l o g n log^n logn 时间可获取最大或最小值。

    我们创建两个堆,一个大顶堆和一个小顶堆,分别维护一部分数据,且大顶堆数据量与小顶堆数据量相等或仅比小顶堆数据量大一。

    假定数据流中有n个数,小顶堆维护数值较大的 n/2 个数,大顶堆维护数值较小的 n/2 个数,那么小顶堆的堆顶值和大顶堆的堆顶值则是数据流的中间数值。

    简单如图示:
    在这里插入图片描述

    已经确定如何处理该问题。现在讨论如何维护大顶堆和小顶堆:

    • 数据流中读入一个数,将其加入小顶堆中。如果小顶堆的顶堆值大于大顶堆的顶堆值,此时需要交换两者的值。
    • 数据流中读入一个数,将其加入小顶堆。如果小顶堆的数据量比大顶堆的数据量大于一,此时应将小顶堆的顶堆值放到大顶堆中。
  • 实现代码:

    /*
    包含头文件
    #include <queue>
    */
    
    priority_queue<int> big_heap; // 大顶堆
    priority_queue<int, vector<int> ,greater<int> > small_heap; // 小顶堆
    
    void insert(int num){
        int tmp;
        big_heap.push(num);
        if((small_heap.size()) && (big_heap.top() > small_heap.top())) // 发生逆序
        {
            tmp = small_heap.top();
            small_heap.pop();
            small_heap.push(big_heap.top());
            big_heap.pop();
            big_heap.push(tmp);
        }
        if(big_heap.size() - small_heap.size() > 1)
        {
            small_heap.push(big_heap.top());
            big_heap.pop();
        }
    }
    
    double getMedian(){
        if((big_heap.size() + small_heap.size()) % 2) // 和为奇数
        {
            return big_heap.top();
        }
        else
        {
            return (big_heap.top() + small_heap.top()) / 2.0;
        }
    }
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值