堆結構的應用--Leecode刷題

我記得以前做題就經常碰到堆,但是也沒有記錄過什麼,今天決定記錄一下堆的應用!

1.找中位數

295. 數據流的中位數

中位數是有序列表中間的數。如果列表長度是偶數,中位數則是中間兩個數的平均值。

例如,

[2,3,4] 的中位數是 3

[2,3] 的中位數是 (2 + 3) / 2 = 2.5

設計一個支持以下兩種操作的數據結構:

void addNum(int num) - 從數據流中添加一個整數到數據結構中。
double findMedian() - 返回目前所有元素的中位數。

示例:
addNum(1)
addNum(2)
findMedian() -> 1.5
addNum(3)
findMedian() -> 2

這道題就是所謂的添加元素,然後找中位數,這題我開始用的是List 加 lower_bound()結果後來超時,後來看了題解用堆確實是好方法!!!

1.你需要維護兩個堆:
priority_queue<int,vector,less> low; (大頂堆)
priority_queue<int,vector,greater> up;(小頂堆)

一個堆用來存放一半小數字(low),一半大數字(up).
如圖(紅色是low堆的值,藍色應該是up堆的值)

之後變成堆的結構應該如下圖:
在這裏插入圖片描述

其實很容易看出來,如果爲單數,取的就是大頂堆(low)的頂,若爲偶數,就取大頂堆和小頂堆頂和除2!

2.關於添加數字。如何添加,若添加的數字num大於up頂的值,很明顯,應該添加到up裏面,其他情況添加到low裏面。之後保證low中的值永遠大於up的值+1或者數量相等,適當的把兩者的top值移動,保持上述條件即可。
代碼如下

class MedianFinder {
public:
    /** initialize your data structure here. */
    priority_queue<int,vector<int>,less<int>> low;
    priority_queue<int,vector<int>,greater<int>> up;
   
    MedianFinder() {

    }

    void addNum(int num) {

       if(!up.empty()&&num > up.top()) up.push(num);
       else low.push(num);

       if(low.size() > up.size()+1){
           up.push(low.top());
           low.pop();
       }

       if(low.size() < up.size()){
           low.push(up.top());
           up.pop();
       }
    }

    double findMedian() {
       if(low.size() > up.size()) return double(low.top());
       else return double(low.top()+up.top())/2;
    }
};

(圖片借用了Leecode)

未完待續…

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