思路是動態維護對頂堆,使用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;
}
};