单调队列
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;
}