LeetCode HOT100 - 滑动窗口最大值
滑动窗口移动的过程就是不断有元素进/出的过程
要维护这个过程中现有元素的最大值
那最基础的就是维护一个元素有没有出现
但是一个窗口中可能有多个相同元素,因此再加上元素的出现次数
因此一个数组来维护出现次数,一个优先队列来维护现有元素
每次移动同步对元素进行更新维护
class Solution {
public:
vector<int> maxSlidingWindow(vector<int>& a, int k) {
unordered_map<int, int> cnt;
priority_queue<int, vector<int>> pq;
for (int i = 0; i < k; i++) {
cnt[a[i]]++;
if (cnt[a[i]] == 1) {
pq.push(a[i]);
}
}
int n = a.size();
vector<int> ans;
ans.emplace_back(pq.top());
for (int l = 0, r = k; r < n; l++, r++) {
cnt[a[l]]--;
cnt[a[r]]++;
if (cnt[a[r]] == 1) {
pq.emplace(a[r]);
}
while (!pq.empty() && cnt[pq.top()] == 0) {
pq.pop();
}
ans.emplace_back(pq.top());
}
return ans;
}
};
正解是双端队列
同样还是考虑我们要什么
我们要的是区间中元素的最大值
我们前面用的是优先队列
但这样需要额外维护次数
因为我们每次插入的时候是把元素交给优先队列处理的,因而丢失了位置信息,所以要通过这种压缩的出现次数来判断是否还在窗口中
那如果我们直接从位置信息,也就是下标入手呢
下标不在窗口区间中那么就是被排除了
这样的话或许自己编写 cmp 去做下标的优先队列也是可行的,就是存下标,但比较比的是下标对应元素的大小
进一步考虑有其他方法吗
优先队列可以看作是维护了一个有序的数组
那我们能不能自己显式地把这个数组刻画出来呢
参考单调栈的想法
做一个单调队列
区别在于,我们这里队列头的元素最大
队列尾的元素最新,这里有些贪心的想法在,新加入的元素是最新的,比它小的元素一定不会在更远的滑动窗口中做出贡献,所以直接删除
class Solution {
public:
vector<int> maxSlidingWindow(vector<int>& a, int k) {
vector<int> ans;
deque<int> q;
int n = a.size();
for (int i = 0; i < k; i++) {
while (!q.empty() && a[i] > a[q.back()]) {
q.pop_back();
}
q.emplace_back(i);
}
ans.emplace_back(a[q.front()]);
for (int i = k; i < n; i++) {
while (!q.empty() && q.front() <= i - k) {
q.pop_front();
}
while (!q.empty() && a[i] > a[q.back()]) {
q.pop_back();
}
q.emplace_back(i);
ans.emplace_back(a[q.front()]);
}
return ans;
}
};

浙公网安备 33010602011771号