一.题意整理

给定一个数组num和一个窗口大小size,求每个连续size序列的最大值。

二.思路整理

首先指出利用c++STL中的max_element也可以AC本题,但是很显然时间复杂度比较高。那么我们可以采用滑动窗口算法来解决,滑动窗口算法本质就是对区间进行扩张和放缩,下面给出滑动窗口的框架

int left = 0, right = 0;
while (right < s.size()) {
     while (window needs shrink) {//对于是否需要进行缩小
        // 缩小窗口
        window.remove(s[left]);
        left++;
    }
    // 增大窗口
    window.add(s[right]);
    right++;
    
    
}
//逻辑框架 结合具体情况而言

对于该题我们最重要的就是维护区间的最大值,我们可以利用双端队列来实现。双端队列是一个可以实现双端插入和删除的队列。我们将会存储每一个数据的下标,既方便比较其是否在区间内又可以快速表示其对应的值。队列中数组下标应当是依次递减的,这是为了通过下标保存当前这个区间下,最大元素的下标始终在队头。对于队列中的元素最需要维护的就是最大值,每一次插入新数据的时候,小于新数据的数据就没有存在的意义可以对其进行出队操作。

下面总结整题思路:

1.双端队列是空,或者当前数据小于队尾的最小数据,直接从队尾入队。
2.双端队列不是空的时候,比较队尾数据,若队尾小于插入元素队尾出队,至队尾元素大于插入元素。
3.由于前面的维护,队头就一直是最大元素。

三.代码实现

class Solution {
public:
    vector<int> maxInWindows(const vector<int>& num, unsigned int size) {
        vector<int>ans;//用来返回最后的最大值
        deque<int>q;
        if(size==0) return ans;
        int i=0;
        while(i<num.size()){
            //缩小窗口
            while(q.size()&&num[q.back()]<num[i]){
                q.pop_back();
            }
            q.push_back(i);
            //说明当前队头已经不在区间中之间出队
            if(q.front()+size<=i){
                q.pop_front();
            }
            //记录最大值
            if(i+1>=size){
                ans.push_back(num[q.front()]);
            }
            i++;
        }
        return ans;
    }
};