剑指offer 数据流中的中位数 c++

题目描述

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

实例输出

随着数据流的增加,不断的更新中位数,并输出
在这里插入图片描述

分析

根据时间效率表发现,用二叉树、AVL数、最大堆和最小堆的效率最高,但由于二叉树和AVL数没有现成的数据结构,所以最终决定用最大堆和最小堆实现。
在这里插入图片描述

思路

  1. 用min堆实现左边的的数据容器,max堆实现右边的数据容器。
  2. 中位数永远放在第一个位置,如果奇数个就直接取min[0],如果偶数就是min[0]和max[0]的平均数
  3. 当前size为奇数则存入max,偶数存入min
  4. 两堆大小之差不能超过1

由实例输出可得
5 -> 5 -------------------------------------(min[0] = 5)
5,2 -> (5+2)/2 = 3.5------------------- (min[0] = 5, max[0] = 2)
5,2,3 -> 3-------------------------------- (min[0] = 3, min[1] = 5, max[0] = 2)
5,2,3,4 -> (3+4)/2 = 3.5-------------- ( min[0] = 3, min[1] = 5, max[0] = 4, max[1] = 2)

代码

class Solution {
public:
    void Insert(int num)
    {
        //even : save num in to min[]
        if(((min.size() + max.size()) & 1 )== 0 ){
            if(min.size() > 0 && num < max[0]){
                max.push_back(num);
                // big -> small
                push_heap(max.begin(), max.end(),less<int>());
                num = max[0];
                pop_heap(max.begin(), max.end(), less<int>());
                max.pop_back();
            }
            min.push_back(num);
            // order heap : small -> big
            push_heap(min.begin(), min.end(), greater<int>());
        }
        //odd : save num in to max[]
        else {
            if(min.size() > 0 && num > min[0]){
                min.push_back(num);
                push_heap(min.begin(),min.end(),greater<int>());
                num = min[0];
                pop_heap(min.begin(),min.end(),greater<int>());
                min.pop_back();
            }
            max.push_back(num);
            push_heap(max.begin(), max.end(), less<int>());
        }
    }

    double GetMedian()
    { 
        int size = min.size() + max.size();
        if( size == 0) return 0;
        // even
        if( size & 1 == 0) {
            return (min[0] + max[0])/2.0;
        }
        else {
            return min[0];
        }
    }

private:
        vector<int> min;
        vector<int> max;
};

关于最大堆和最小堆

Heap in C++ STL
make_heap() : 将数组转成堆形式

    vector<int> v1 = {20, 30, 40, 25, 15}; 
    make_heap(v1.begin(), v1.end()); 

push_heap() : 往堆中加新的元素
pop_heap() : 删除堆中最大的元素

	//INSERT
	//从大到小
    push_heap(v1.begin(), v1.end()); 
    push_heap(v1.begin(),v1.end(),less<int>());
    cout << v1.front();
    //从小到大
    push_heap(v1.begin(),v1.end(),greater<int>());

	//DELETE
	pop_heap(v1.begin(), v1.end()); 
    v1.pop_back(); 

sort_heap() : 排序堆,但排序后不再是堆的形式,默认从小到大

	// 创建向量
    vector<int> v1 = {20, 30, 40, 25, 15}; 
      
    // 转为堆形式
    make_heap(v1.begin(), v1.end()); 
      
    // 输出堆 
    cout << "The heap elements are : "; 
    for (int &x : v1)  
       cout << x << " "; 
       
    cout << endl; 
    
	//排序
	sort_heap(v1.begin(), v1.end()); 
      
     // 输出堆 
    cout << "The heap elements after sorting are : "; 
    for (int &x : v1)  
       cout << x << " "; 

output:

The heap elements are : 40 30 20 25 15
The heap elements after sorting are : 15 20 25 30 40

is_heap() : 判断是否是堆,返回true/false

 is_heap(v1.begin(), v1.end())? 
    cout << "The container is heap ": 
    cout << "The container is not heap"; 
    cout << endl;

is_heap_until() :返回位置

 	// 确认当前位置
    // till which container is heap 
    auto it = is_heap_until(v1.begin(), v1.end()); 
参考网站
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值