单调队列

1. [Leetcode.面试题59]

求给定滑动窗口最大值
输入: nums = [1,3,-1,-3,5,3,6,7], 和 k = 3
输出: [3,3,5,5,6,7] 

暴力O(n*k)代码

vector<int> maxSlidingWindow(vector<int>& nums, int k) {
    vector<int> res;
    for(int i=0; i+k-1<nums.size(); i++) {
          int maxm = -1;
          for(int j=0; j<k; j++)
                maxm = max(maxm, nums[i+j]);
          res.push_back(maxm);
    }
    return res;
}

方法:设想一个单调队列dq以从大到小的顺序来储存窗口中值(如果能保证队列中的值都在窗口内),那么每一次取队列的头就行。
现在我们用dq来储存窗口中的索引数组,每次新来数据时都把索引插队列尾,这样队列是单调递增的,很容易维护它在窗口范围内(删除前面不符合索引范围的值)。
同时还需保证 x[dq[i]] > x[dq[i+1]] 这样每次取 x[dq.front] 就行,因此实际上每次来新的数据时,就得找到它要插入的位置,并且保证队列中至少有一个值,因此也就可以把插入点之后的全部删光。

vector<int> maxSlidingWindow(vector<int>& nums, int k) {
    vector<int> res;
    deque<int> dq;
    if(nums.size() == 0) return res;
    for(int i=0; i<nums.size(); i++) {
          while(!dq.empty() &&  i-dq.front()+1>k) 
                dq.pop_front(); // 队列中储存的索引值在窗口范围内
          while (!dq.empty() && nums[dq.back()] <= nums[i])
                dq.pop_back(); // 找到插入位置, 删光后面的值
          dq.push_back(i);
          if(i >= k-1) res.push_back(nums[dq.front()]);
    }
    return res;
}
原文地址:https://www.cnblogs.com/xytpai/p/12846401.html