剑指offer 数据流中的中位数

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

首先在剑指offer上这个题目说的不是很清楚,两个函数的意思是,一个Insert函数代表插入一个数到序列中,而GetMedian函数表示返回一个中位数。

思路:
首先根据题目描述,可以试想将数据分为两个堆,一个最大堆一个最小堆,因为中位数的一个性质是比前面一半的元素都大比后面一半的元素都小,所以可以建两个堆,但是在STL中没有堆的数据结构而是用优先队列实现的priority_queue。默认情况下优先队列是最大堆,所以接下来处理是如果加入一个数序列具有奇数个,然后就放到最小堆,偶数个就放到最大堆,但是还有一个问题存在,如果直接放到最大堆,但是如果这个数比右边的最小堆中的某个数大,那么就违反了中位数的性质,所以可以先将这个数放到最小堆中,然后取最小值(时间复杂度O(1))放到最大堆中,那么就满足了中位数的性质,相当于一个调整的过程,反之亦然。
代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;

priority_queue<int>big;//大根堆
priority_queue<int,vector<int>,greater<int> >small;//小根堆
void Insert(int num)
{
    int s1 = big.size();
    int s2 = small.size();
    if((s1+s2)%2==0)
    {
        small.push(num);
        big.push(small.top());
        small.pop();
    }
    else
    {
        big.push(num);
        small.push(big.top());
        big.pop();
    }
}

 double GetMedian()
 {
    int s1 = small.size();
    int s2 = big.size();
    double ans;
    if((s1+s2)%2==0) ans = (small.top()+big.top())*1.0/2;
    else ans = big.top()*1.0;
    return ans;
 }

int main()
{
    int a[] = {5,7,9,4,3,10};
    for(int i=0;i<6;i++)
    {
        Insert(a[i]);
        printf("%lf\n",GetMedian());
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值