剑指Offer——JZ64.滑动窗口的最大值【单调队列】

题目传送门


在这里插入图片描述


题解

  • 可以暴力求解,时间复杂度 O ( n k ) O(nk)
  • 考虑 i i i + 1 i+1 共存的区间:
  • 如果 n u m [ i ] < = n u m [ i + 1 ] num[i]<=num[i+1] ,那么无须考虑 n u m [ i ] num[i]
  • 如果 n u m [ i ] > n u m [ i + 1 ] num[i]>num[i+1] ,那么需要保留 n u m [ i + 1 ] num[i+1] ,因为,当 n u m [ i ] num[i] 不在区间内的时候, n u m [ i + 1 ] num[i+1] 可能是最大值。
  • 所以我们可以维护一个单调双端队列,当前窗口新增第 i i 个元素:
  • > n u m [ i ] 队尾>num[i] ,那么放入队列尾
  • < = n u m [ i ] 队尾<=num[i] ,那么说明,当 n u m [ i ] num[i] 来了的时候,前面小的就不用考虑了,删除即可。
  • 因为每次新增一个元素,那么窗口就要退出一个元素,我们双端队列记录的是下标,那么每次判断队首下表是否合法即可。
  • 最后队首就是当前窗口最大值。
  • 注意:size是unsigned int 减法的时候需要强转,否则会出错

AC-Code

class Solution {
public:
    vector<int> maxInWindows(const vector<int>& num, unsigned int size) {
        vector<int> ans;
        deque<int> dque;
        for(int i = 0; i < num.size(); ++i) {
            while(!dque.empty() && num[dque.back()] <= num[i])
                dque.pop_back();
            dque.push_back(i);
            if(dque.front() <= i - (int)size)
                dque.pop_front();
            if(i >= size - 1)
                ans.push_back(num[dque.front()]);
        }
        return ans;
    }
};

猜你喜欢

转载自blog.csdn.net/Q_1849805767/article/details/106555381