1. 程式人生 > 其它 >劍指offer——資料流中的中位數C++(堆-優先佇列)

劍指offer——資料流中的中位數C++(堆-優先佇列)

技術標籤:劍指Offer#佇列演算法資料結構優先佇列劍指offer

在這裡插入圖片描述
vector加sort不香嗎,時間複雜度O(nlogn),實際執行比這個更快誒。雖香但滾。
因為是中位數,所以把左右分成兩塊,左邊是大頂堆,右邊是小頂堆。堆的插入時間複雜度為O(lgn),取值的時間複雜度就是O(1),因為就是取兩個堆頂的操作。插入滿足兩個操作:1.兩邊的資料量之差不大於1,2.且左邊全小於右邊。
所以我們的插入操作是,當前資料總量是偶數時,將其插入左堆(過程是先插入右,再將右的堆頂插入到左堆),奇數時反向操作。這樣子就可以保證左堆>=右堆,且左邊一定小於右邊。取值時當前為奇數,就去左堆堆頂取,為偶數時,就取兩個堆頂/2,記得都轉為double

class Solution {
public:
    //法1,用一個vector每次插入後排序,然後插入後排序
    //法2:左邊一個大頂堆,右邊一個小頂堆
    //最小堆的插入時間複雜度是O(lgn),取值是O(1),因為就是取兩個堆頂的值即可
    //最主要是插入時要保證兩點,兩邊的資料量不大於1,且左邊全部小於右邊
    //當前資料量是偶數時,先將值插入右邊(小頂堆),然後彈出堆頂元素插入大頂堆
    //當前資料量是奇數時,先將值插入左邊(大頂堆),然後彈出堆頂元素插入小頂堆
    //此時一定能保證以上兩點全部滿足
    //取中位數時,當前資料量為奇數時,取大頂堆首部,如果是偶數,就取兩個堆頂平均值
void Insert(int num) { if((left.size() + right.size()) % 2 == 0){ right.push(num); //可以erase(right.begin())或者right.pop即可 left.push(right.top()); right.pop(); } else{ left.push(num); right.push(left.
top()); left.pop(); } } double GetMedian() { if((left.size()+right.size())%2 ==1){ return double(left.top()); } else return double(left.top()+right.top())/2; } private: //less是從大到小(大頂堆),greater是從小到大(小頂堆) //left是大頂堆左邊的 priority_queue<int,vector<int>,less<int>> left; priority_queue<int,vector<int>,greater<int>> right; };