方法:双向队列

双向队列就是一种特殊的队列,双向队列两边,即头部和尾部都可以进行插入元素和删除元素的操作,但是也只能插入到最尾部或者最头部,每次也只能取出头部元素或者尾部元素后才能取出里面的元素。

具体做法:

  • step 1:维护一个双向队列,用来存储数列的下标。
  • step 2:首先检查窗口大小与数组大小。
  • step 3:先遍历第一个窗口,如果即将进入队列的下标的值大于队列后方的值,依次将小于的值拿出来去掉,再加入,保证 队列是递增序。
  • step 4:遍历后续窗口,每次取出队首就是最大值,如果某个下标已经过了窗口,则从队列前方将其弹出。
  • step 5:对于之后的窗口,重复step 3,直到数组结束。

时间复杂度:o(n)。

空间复杂度:o(n)。

class Solution {
  public:
    vector<int> maxInWindows(vector<int>& num, int size) {
        vector<int> res;
        //特殊情况处理
        if (size > num.size() || size == 0)
            return res;

        deque<int> temp;
        //遍历第一个窗口
        for (int i = 0; i < size; i++) {
            //去掉比自己先进入队列的小于自己的值
            while(!temp.empty() && num[i] > num[temp.front()])
                temp.pop_back();
            temp.push_back(i);
        }

        for (int i = size; i < num.size(); i++) {
            //每移动一位,将窗口最大值推入数组
            res.push_back(num[temp.front()]);
            //当滑动窗口移动到超出队列头元素时,弹出队列头元素
            while (!temp.empty() && temp.front() < i - size + 1)
                temp.pop_front();
            //每移动一次,将前面小于当前值的序列全部弹出
            while (!temp.empty() && num[i] > num[temp.back()])
                temp.pop_back();

            temp.push_back(i);
        }
        //将最后一个滑动窗口的最大值推入数组
        res.push_back(num[temp.front()]);

        return res;
    }
};