數據流中的中位數(劍指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];
        }
        
    }

};

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