【剑指offer-解题系列(64)】数据流中的中位数

题目描述

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

分析

使用两个堆排数组,一个最大堆(前半段数据),一个最小堆(后半段数据)。
两个堆总共只有两种情况:
1、最大堆和最小堆数量相等(此时返回两个堆顶数目的相加平均)
2、最小堆数量多一个(返回最小堆顶元素)

如果新来的数字大于最小堆堆顶(属于后半段),那么塞入后半段数组
如果新来的属于前半段,塞入前半段数组

如果发现两边数目不均衡(最小堆-最大堆数目  超过1),则将进行最小堆顶元素给到最大堆,并且调整两个堆

代码实现

vector<int>min_half; // 最大堆
vector<int>max_half; // 最小堆
void Insert(int num)
{
    if(min_half.size()<=0){
        min_half.push_back(num);
        return;
    }
    if(max_half.size()<=0){
        max_half.push_back(num);
        if(max_half[0]<min_half[0])swap(max_half[0],min_half[0]);
        return;
    }
    if(min_half.size()==max_half.size()){
        if(num>min_half[0]){
            min_half.push_back( min(num,max_half[0]));
            max_half[0]=max(num,max_half[0]);
            
            HeapAdjustMax(min_half,0,min_half.size()-1);
            HeapAdjustMin(max_half,0,max_half.size()-1);
        }
        else{
            min_half.push_back(num);
            HeapAdjustMax(min_half,0,min_half.size()-1);
        }
    }
    else{
        if(num>min_half[0]){
            max_half.push_back(num);
            HeapAdjustMin(max_half,0,max_half.size()-1);
        }
        else{
            
            
            max_half.push_back( max(num,min_half[0]));
            min_half[0]=min(num,max_half[0]);
            
            HeapAdjustMax(min_half,0,min_half.size()-1);
            HeapAdjustMin(max_half,0,max_half.size()-1);
        }
    }
    
}




double GetMedian()

    if(min_half.size()==max_half.size()+1){
        return min_half[0];
    }
    else
        return 0.5*min_half[0]+0.5*max_half[0];
}


void HeapAdjustMax(vector<int>&a,int start,int end){
    if(start>=end)
        return ;
    for(int i =end;i>=start;i--){
        int left = 2*i+1;
        int right= 2*i+2;
        if(left<=end){
            if(right<=end){
                if(a[right]>a[left] && a[right]>a[i])
                    swap(a[i],a[right]); 
                else if(a[left]>a[i] && a[left]>a[right])
                    swap(a[i],a[left]);
            }
            else
                if(a[left]>a[i])
                    swap(a[i],a[left]);
        }
    }
}


void HeapAdjustMin(vector<int>&a,int start,int end){
    if(start>=end)
        return ;
    for(int i =end;i>=start;i--){
        int left = 2*i+1;
        int right= 2*i+2;
        if(left<=end){
            if(right<=end){ 
                if(a[right]<a[left] && a[right]<a[i])
                    swap(a[i],a[right]); 
                else if(a[left]<a[i] && a[left]<a[right])
                    swap(a[i],a[left]);
            }
            else
                if(a[left]<a[i])
                    swap(a[i],a[left]);
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值