题意
给你一个数组 nums,有一个长度为 k 的窗口从最左端滑动到最右端。窗口中有 k 个数,每次窗口向右移动 1 位。你的任务是找出每次窗口移动后得到的新窗口中元素的中位数,并输出由它们组成的数组。$(n, k \in [1, 100000])$
Solution
用优先队列+延迟删除有点麻烦,可以考虑直接用 multiset 做,本质都是一样的,维护两个大小相同或差一的集合(自动排序)$l 和 r$,$l$ 维护小于等于中位数的值,$r$ 维护大于等于中位数的值,$multiset$ 的优秀特性可以在 $log$ 时间复杂度内进行增删操作。具体细节较多,时间复杂度 $O(nlog(k))$。
Code
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 
 | class Solution {public:
 vector<double> medianSlidingWindow(vector<int>& a, int k) {
 multiset<double> l, r;
 int n = a.size();
 vector<double> res;
 for (int i = 0; i < n; i++) {
 if (i >= k) {
 if (l.count(a[i - k])) l.erase(l.find(a[i - k]));
 else r.erase(r.find(a[i - k]));
 }
 l.insert((double)a[i]);
 while (l.size() && r.size() && *(--l.end()) > *r.begin()) {
 l.insert(*r.begin());
 r.insert(*(--l.end()));
 l.erase(*(--l.end()));
 r.erase(*r.begin());
 }
 while (l.size() - 1 > r.size()) {
 r.insert(*(--l.end()));
 l.erase(--l.end());
 }
 if (i >= k - 1) {
 if (k & 1) res.push_back(*(--l.end()));
 else res.push_back((*(--l.end()) + *r.begin()) / 2.0);
 }
 }
 return res;
 }
 };
 
 |