运用单调队列的知识点
最直接的做法就是暴力,就是每一个窗口都去遍历一遍窗口内的元素,找到其中的最大值。但很明显这样的时间复杂度是n * k。如果我们用单调队列的话那么只需要遍历一次数组即可,时间复杂度是n
我们要模拟一个队列,像题目中所描述的窗口一样在滑动的时候弹出队列前端的第一个元素同时队列后端入队一个元素。但是我们要获取这个窗口也就是队列的最大值,因此这个队列必须是单调的。但是这个队列不能是优先队列,因为优先队列排序后不能够模拟窗口移动时要移除的元素。
继续思考我们还会发现,在不改变元素的顺序时,是没有必要去维护当前窗口内最大元素外的其他元素的。
要实现单调队列,最重要的是解决每一道题目对应的条件。这道题目中推入元素时如果队尾的元素比此时的元素要小,则弹出队尾元素,直到队尾元素大于或等于此元素。同时每遍历到数组中第i个元素,要判断第i- k个元素是否位于上一个窗口前面,如果是则要弹出。这样才能模拟窗口移动时元素的移除方式同时对队列内的元素进行排序,保证此时窗口内最大的元素位于队列第一个。
代码实现:
class Solution {
public:
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
vector<int> result;
deque<int> w;
int i = 0, j = k;
for (i = 0; i < k; i++) {
while (!w.empty() && w.back() < nums[i])
w.pop_back();
w.push_back(nums[i]);
}
result.push_back(w.front());
for (; i < nums.size(); i++) {
if (!w.empty() && w.front() == nums[i - k])
w.pop_front();
while (!w.empty() && w.back() < nums[i])
w.pop_back();
w.push_back(nums[i]);
result.push_back(w.front());
}
return result;
}
};