滑动窗口的最大值

每天学一点,今天解决的是剑指offer的剑指 Offer 59 - I. 滑动窗口的最大值。
输入: 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 3
1 [3 -1 -3] 5 3 6 7 3
1 3 [-1 -3 5] 3 6 7 5
1 3 -1 [-3 5 3] 6 7 5
1 3 -1 -3 [5 3 6] 7 6
1 3 -1 -3 5 [3 6 7] 7

可以用暴力法强行破解,但是复杂度无法保证,因此可以考虑滑动窗口,在滑动窗口的思路。
我开始想到每次滑动后都将窗口内的元素进行排序为递减序列,弹出队首作为该滑动窗口的最大值,但是一旦进行排序,就会打乱顺序,那么我怎么保证滑动窗口进行移动时弹出哪个元素?
因此,我们的队列需要满足两个要求

  1. 队首为该滑动序列的最大值
  2. 排序后的队列在滑动窗口移动时不需要考虑弹出的元素顺序被打乱。
    根据这些特点,单调的双向队列可以满足我们。
    其特点为,整个队列是单调递减的,队首元素为当前元素最大值。

为什么需要双向队列?需要对队伍两端进行操作,为什么要对队伍两端进行操作因为

  1. 队首删除是因为滑动窗口的长度已经过长了,需要对队首元素进行删除操作。
  2. 队尾删除是因为新插入的元素比队尾的元素大,为了维持队伍的单调性,因此需要删除队尾元素把新插入的元素加上

这样队伍的元素顺序就与所给数组的元素相对顺序相同,且从大到小进行排序,具体到代码如下。

class Solution {
public:
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
       int n =nums.size();
       if(n<k || k<=0)
       return {};//防止传入错误的参数
        int low = 1-k,high = 0;
        deque<int> dp;
        vector<int> res;

        while(high < n ){
            //  判断滑窗的low是否为最大元素
            if(low >= 1 && nums[low -1] == dp[0])/滑动窗口太长了或者左端就是最大元素
            dp.pop_front();//删掉队首

            while(!dp.empty() && dp[0]<nums[high])
            dp.pop_front();//小于nums[high]都删掉
            while(!dp.empty() && dp[dp.size()-1]<nums[high])
            dp.pop_back();//清空比nums[high]小的元素
            dp.push_back(nums[high]);//插入nums[high]

            if(low >=0)//如果low>=0说明已经是一个完整的滑动窗口了
            res.push_back(dp[0]);//插入队首元素
            low++;
            high++;


        }
return res;
        


    }
};
©️2020 CSDN 皮肤主题: 书香水墨 设计师:CSDN官方博客 返回首页