数据流中的中位数(剑指offer 面试题41)

题目描述:

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

解题思路:

本题对数据流求取中位数,要考虑数据插入数据结构和求取中位数的时间开销;本文利用vector数组,采用大顶堆和小顶堆的数据结构存储数据流,如果数据流是偶数,则大顶堆和小顶堆的元素数量相同,如果是奇数,小顶堆的元素比大顶堆的元素个数多1;小顶堆的最小值(开头处)比大顶推的最大值(开头处)大;这样中位数的获取,如果是奇数,就是小顶推的最小值(开头处),否则是(小顶堆的最小值+大顶推的最大值)/2。整个算法,插入数据的时间开销是O(logn),获取中位数的时间开销为O(1);

注意:

1)push_heap(),pop_heap(),make_heap(),sort_heap()的用法参考https://blog.csdn.net/qq_34793133/article/details/81222919

2)less<T>() 对于vector模拟堆而言表示大顶堆,greater<T>()表示小顶堆;

而对set,multiset而言 less<T>()表示小顶堆,greater<T>()表示大顶堆。

通过的C++代码:

class Solution {
public:
    vector<int> bigTopHeap;
    vector<int> smallTopHeap;
    void Insert(int num)
    {
        if(((bigTopHeap.size() + smallTopHeap.size()) & 1) == 0)
        {
            if(bigTopHeap.size() > 0 && num < bigTopHeap[0])
            {
                bigTopHeap.push_back(num);
                push_heap(bigTopHeap.begin(), bigTopHeap.end(), less<int>());
                
                num = bigTopHeap[0];
                pop_heap(bigTopHeap.begin(), bigTopHeap.end(),less<int>());
                bigTopHeap.pop_back();
            }
            smallTopHeap.push_back(num);
            push_heap(smallTopHeap.begin(), smallTopHeap.end(), greater<int>());
        }
        else
        {
            if(smallTopHeap.size() > 0 && num > smallTopHeap[0])
            {
                smallTopHeap.push_back(num);
                push_heap(smallTopHeap.begin(), smallTopHeap.end(), greater<int>());
                
                num = smallTopHeap[0];
                pop_heap(smallTopHeap.begin(), smallTopHeap.end(), greater<int>());
                smallTopHeap.pop_back();
            }
            bigTopHeap.push_back(num);
            push_heap(bigTopHeap.begin(), bigTopHeap.end(), less<int>());
        }
    }

    double GetMedian()
    {
        int cout = bigTopHeap.size() + smallTopHeap.size();
        if(cout == 0)
            return 0.0;
            //throw exception("No numbers are avilable");
        if((cout & 1) == 0)
        {
            return (bigTopHeap[0]+smallTopHeap[0])/2.0;
        }
        else
        {
            return smallTopHeap[0];
        }
        
    }

};

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章