Leetcode 480. 滑動窗口中位數 (滑動窗口維護中位數,使用兩個multiset替代對頂堆)

思路是動態維護對頂堆,使用multiset代替堆,避免手動實現堆的刪除。

class Solution {
public:
    double find_median(multiset<int> &min, multiset<int> &max, int k){
        if(k%2==0){
            return ((double)*max.rbegin()+*min.begin())/2;
        }else{
            return *max.rbegin();
        }
    }
    vector<double> medianSlidingWindow(vector<int>& nums, int k) {
        // 從數據流的中位數進階過來
        // 使用對頂堆,大根堆存前k/2的元素,小根堆存後k/2個元素
        // 滑動窗口,需要對支持刪除操作。
        // STL裏面的堆不支持刪除元素,用multiset替代
        // 定義上min總是比max多一個
        multiset<int> max, min;
        vector<double> res;
        for(int i=0;i<k;i++){
            max.insert(nums[i]);
        }
        for(int i=0;i<k/2;i++){
            auto tmp = *max.rbegin();
            max.erase(max.find(tmp));
            min.insert(tmp);
        }
        auto tmp = find_median(min,max,k);
       // cout<<tmp<<endl;
        res.push_back(find_median(min,max,k));
        for(int i=k;i<nums.size();i++){
            if(nums[i]<=*max.rbegin()){
                max.insert(nums[i]);
            }else{
                min.insert(nums[i]);
            }
            if(nums[i-k]<=*max.rbegin()){
                max.erase(max.find(nums[i-k]));
            }else{
                min.erase(min.find(nums[i-k]));
            }
            while(min.size()>=max.size()){
                auto tmp = *min.begin();
                min.erase(min.find(tmp));
                max.insert(tmp);
            }
            while(max.size()>min.size()+1){
                auto tmp = *max.rbegin();
                max.erase(max.find(tmp));
                min.insert(tmp);
            }
            auto tmp = find_median(min,max,k);
            res.push_back(tmp);
        }
        return res;
    }
};

 

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