【剑指offer】面试题41:数据流中的中位数【C++版本】

20180601

总结的部分题目思路与代码,待完善。
【剑指offer-第二版】部分题目与解答【C++版本】

题目:

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

解题思路:

1.本来使用一个AVL树来实现是最佳的,但是各种语言的函数库都还没有现成的AVL树的实现,所以选择使用两个堆来完成。使用一个最大堆实现中位数左边的数据容器,使用一个最小堆实现中位数右边的数据容器。往堆中插入一个数据的时间是O(logn),而取得最大最小数据的时间是O(1)。

注意:

1.必须保证数据平均分配到两个堆中间,即两个堆中的数据数目之差不能超过1。为了实现数据的平均分配,可以在数据的总数目是偶数是把新数据插入到最小堆中,否则插入到最大堆中。
2.还必须保证最小堆中的所有数据都要大于最大堆中的数据。比如在偶数个数据时,如果要插入的数据小于最大堆的一些数据,需要把数据先插入最大堆,然后把最大堆的最大数据弹出,再插入到最小堆中。奇数个数的数据插入时也相同。
3.在《剑指offer》的标准解法中,使用了STL函数push_heap,pop_heap等。 STL中heap相关函数的用法

C++代码实现(可AC)
//和《剑指offer》上的思路一样,不过改成了第偶数个数据加入最小堆,第奇数个数据加入最大堆
#include <vector>
#include <iostream>
#include <algorithm>

using namespace std;

class toGetMedian{
public:
    void Insert(int num)
    {
       int size = maxheap.size() + minheap.size();
       if(size&1){                                   //第偶数个的情况
            int tmp = num;
            if((!maxheap.empty())&&(num < maxheap[0])){
                tmp = maxheap[0];
                maxheap[0] = num;
                make_heap(maxheap.begin(),maxheap.end());
            }   

            minheap.push_back(tmp);
            push_heap(minheap.begin(),minheap.end(),greater<int>());
       }
       else{
            int tmp = num;
            if((!minheap.empty())&&(num > minheap[0])){
                tmp = minheap[0];
                minheap[0] = num;
                make_heap(minheap.begin(),minheap.end(),greater<int>());
            }   

            maxheap.push_back(tmp);
            push_heap(maxheap.begin(),maxheap.end());
       }
    }  

    double GetMedian()
    {
        int size = maxheap.size() + minheap.size();
        double resu;
        if(size & 1){
            resu = maxheap[0];
        }   
        else{
            resu =  (maxheap[0] + minheap[0])/2.;
        }   

        return resu;
    }   
private:
    vector<int> maxheap;
    vector<int> minheap;
}; 

int main()
{
    toGetMedian test;
    test.Insert(1);
    test.Insert(9);
    test.Insert(3);
    test.Insert(6);
    test.Insert(20);
    test.Insert(82);

    cout << test.GetMedian() << endl;

    return 0;
} 
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值