滑动窗口: 一般使用双指针算法,左指针l和右指针r之间的空间称为窗口,由于指针是不断移动的,从而窗口也可以移动,称为滑动窗口。
滑动窗口的最值: 由于窗口是移动的,移动的过程中有新元素的加入也有旧元素的弹出。每一次元素的加入或弹出都可能使窗口中元素的最值发生变化,也正是会发生变化,使得无法直接获取任意时刻滑动窗口的最值。
单调队列求滑动窗口最值: 虽然滑动窗口中不断有新元素加入和旧元素弹出,但是始终都有一个特点就是新元素都是从右指针r处加入的,旧元素都是从左指针l处弹出的。当一个元素如果是当前窗口的最大值,则它前面的值就不需要保存,因为只要它在窗口中,最值就不会变成其他的值,而对于它后面的比它小的元素则要保存,因为它一点弹出,最大值就要发生变化,需要保存后面的比它小的值。类似可推最小值。
双端队列: 使用双端队列,维持队列是一个单调队列(最大值: 单调递增队列,最小值: 单调递减队列),每次最值就是双端队列的front
// LeetCode 1438. 绝对差不超过限制的最长连续子数组
deque<int> maxx;
deque<int> minn;
while(r < sz){
while (!maxx.empty() && nums[r] > maxx.back()) maxx.pop_back();
while (!minn.empty() && nums[r] < minn.back()) minn.pop_back();
maxx.push_back(nums[r]);
minn.push_back(nums[r]);
while(l < r && abs(maxx.front() - minn.front()) > limit){
if (nums[l] == maxx.front()) maxx.pop_front();
if (nums[l] == minn.front()) minn.pop_front();
l ++;
}
if (abs(maxx.front() - minn.front()) <= limit){
ans = max(ans, r - l + 1);
}
++r;
}