一、题目描述
给你一个整数数组 nums
,有一个大小为 k
的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k
个数字。滑动窗口每次只向右移动一位。
返回滑动窗口中的最大值。
示例 1:
输入:nums = [1,3,-1,-3,5,3,6,7], k = 3
输出:[3,3,5,5,6,7]
解释:
滑动窗口的位置 最大值
[1 3 -1] -3 5 3 6 7 31 [3 -1 -3] 5 3 6 7 31 3 [-1 -3 5] 3 6 7 51 3 -1 [-3 5 3] 6 7 51 3 -1 -3 [5 3 6] 7 61 3 -1 -3 5 [3 6 7] 7示例 2:
输入:nums = [1], k = 1
输出:[1]
二、题解
自定义一个保存所有可能的最大值的降序单调队列,时间复杂度和空间复杂度均为 O ( n ) O(n) O(n)。
这个单调队列的内部元素从队头到队尾依次减小,且对出队和入队有以下说明:
- 窗口移动前,窗口最左侧的值
val
如果刚好等于队头,那么说明当前的最大值会受影响,队头需要出队,而如果val
小于队头,那么最大值不受影响。 - 窗口移动后,窗口最右侧的值
val
需要入队,但在入队前需要弹出队尾所有小于val
的元素,因为由于val
的出现,这些旧的元素永远无法成为最大值,就算现在不把它们弹出,他们也会先于更大的val
弹出。
class Solution {
private:class MaxQueue {private:deque<int> m_queue;public:void push(int val) {while (!m_queue.empty() && val > m_queue.back()) {m_queue.pop_back();}m_queue.emplace_back(val);}void pop(int val) {if (val == m_queue.front()) {m_queue.pop_front();}}int front() {return m_queue.front();}};public:vector<int> maxSlidingWindow(vector<int> &nums, int k) {vector<int> result;MaxQueue q;for (int i = 0; i < k; i++) {q.push(nums.at(i));}result.emplace_back(q.front());for (int i = k; i < nums.size(); i++) {q.pop(nums.at(i - k));q.push(nums.at(i));result.emplace_back(q.front());}return result;}
};