劍指offer - 63數據流中的中位數

題目描述

如何得到一個數據流中的中位數?如果從數據流中讀出奇數個數值,那麼中位數就是所有數值排序之後位於中間的數值。如果從數據流中讀出偶數個數值,那麼中位數就是所有數值排序之後中間兩個數的平均值。我們使用Insert()方法讀取數據流,使用GetMedian()方法獲取當前讀取數據的中位數。

有下面兩種思路:

1. 使用一個數組保存數據流中的數據,每次insert時,使用插入排序,保證數組中的數據是從小到大排序的

2. 使用一個大頂堆和一個小頂堆保存數據,每次insert時,使大頂堆的元素都小於小頂堆的元素,並且兩個堆的大小不超過2,這樣,中位數就在兩個堆頂之中,這種思路其實類似於平衡二叉樹

代碼如下:

class Solution {
public:
    //方法一: 使用數組保存數據流,每次插入時,從小到大排序
    vector<int> array;
    void insert_array(int num){
        array.push_back(num);
        for(int i = array.size()-1; i > 0; i--){
            if(array[i] < array[i-1]){
                array[i] ^= array[i-1];
                array[i-1] ^= array[i];
                array[i] ^= array[i-1];
            }
            else{
                break;
            }
        }
    }
    double get_array_median(){
        int size = array.size();
        if(size % 2 == 1){
            return array[size / 2];
        }
        else{
            return (array[size / 2] + array[size / 2 - 1]) / 2.0;
        }
    }
    
    //方法二:使用一個大頂堆和一個小頂堆保存數據
    //保證大頂堆的數,都小於小頂堆的數, 則滿足排序要求
    //每次你新來的數 先判斷可以放到哪一個堆中
    //保證兩個堆的個數的差,不大於1,則平均值就在兩個堆頂之中
    priority_queue<int, vector<int>, less<int> > p;    //大頂堆
    priority_queue<int, vector<int>, greater<int> > q; //小頂堆
    void insert_heap(int num){
        if(p.empty() || num < p.top()){
            p.push(num);
        }
        else{
            q.push(num);
        }
        if(p.size() == q.size() + 2){
            q.push(p.top());
            p.pop();
        }
        if(p.size() == q.size() - 2){
            p.push(q.top());
            q.pop();
        }
        
    }
    double get_heap_median(){
        if(p.size() == q.size()){  //兩個堆元素個數相同,則結果是堆頂的平均值
            return (p.top() + q.top()) / 2.0;
        }
        else{
            return p.size() > q.size() ? p.top() : q.top();  //哪個堆個數大,則結果就是哪個堆的堆頂
        }
    }
    
    void Insert(int num){
        //insert_array(num);
        insert_heap(num);
    }

    double GetMedian() { 
        //return get_array_median();
        return get_heap_median();
    }

};

 

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