剑指offer - 63数据流中的中位数

题目描述

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

有下面两种思路:

1. 使用一个数组保存数据流中的数据,每次insert时,使用插入排序,保证数组中的数据是从小到大排序的

2. 使用一个大顶堆和一个小顶堆保存数据,每次insert时,使大顶堆的元素都小于小顶堆的元素,并且两个堆的大小不超过2,这样,中位数就在两个堆顶之中,这种思路其实类似于平衡二叉树

代码如下:

class Solution {
public:
    //方法一: 使用数组保存数据流,每次插入时,从小到大排序
    vector<int> array;
    void insert_array(int num){
        array.push_back(num);
        for(int i = array.size()-1; i > 0; i--){
            if(array[i] < array[i-1]){
                array[i] ^= array[i-1];
                array[i-1] ^= array[i];
                array[i] ^= array[i-1];
            }
            else{
                break;
            }
        }
    }
    double get_array_median(){
        int size = array.size();
        if(size % 2 == 1){
            return array[size / 2];
        }
        else{
            return (array[size / 2] + array[size / 2 - 1]) / 2.0;
        }
    }
    
    //方法二:使用一个大顶堆和一个小顶堆保存数据
    //保证大顶堆的数,都小于小顶堆的数, 则满足排序要求
    //每次你新来的数 先判断可以放到哪一个堆中
    //保证两个堆的个数的差,不大于1,则平均值就在两个堆顶之中
    priority_queue<int, vector<int>, less<int> > p;    //大顶堆
    priority_queue<int, vector<int>, greater<int> > q; //小顶堆
    void insert_heap(int num){
        if(p.empty() || num < p.top()){
            p.push(num);
        }
        else{
            q.push(num);
        }
        if(p.size() == q.size() + 2){
            q.push(p.top());
            p.pop();
        }
        if(p.size() == q.size() - 2){
            p.push(q.top());
            q.pop();
        }
        
    }
    double get_heap_median(){
        if(p.size() == q.size()){  //两个堆元素个数相同,则结果是堆顶的平均值
            return (p.top() + q.top()) / 2.0;
        }
        else{
            return p.size() > q.size() ? p.top() : q.top();  //哪个堆个数大,则结果就是哪个堆的堆顶
        }
    }
    
    void Insert(int num){
        //insert_array(num);
        insert_heap(num);
    }

    double GetMedian() { 
        //return get_array_median();
        return get_heap_median();
    }

};

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值