ac_154滑动窗口
题目描述
题目大意&链接
给定一个长度为 n 的数组,和一个大小为 k 的滑动窗口,滑动窗口从数组的最左端移动到最右端,每次移动一个位置,要求输出每个窗口中的最小值和最大值。
输入输出样例:
输入:
8 3
1 3 -1 -3 5 3 6 7
输出:
-1 -3 -3 -3 3 3
3 3 5 5 6 7
详情:ac_154滑动窗口
解题思路
单调队列:队列中的元素保持单调递增或单调递减:
- 对于最小值问题,维护一个单调递增队列:队列头部是当前窗口的最小值,新元素入队时,删除队列中所有比它大的元素,以保持队列单调递增。
int hh = 0, tt = -1;
for (int i = 0; i < n; i++)
{
//判断队头元素是否还在队列里面,不应该在,则弹出队头元素(保持 k 个元素)
if (hh <= tt && i - k + 1 > q[hh]) hh++;
//队列不为空且队尾元素大于等于 x 时,弹出队尾元素(使队列具有单调性)
while (hh <= tt && a[q[tt]] >= a[i]) tt--;
//当前元素下标 i 入队
q[++tt] = i;
if (i >= k - 1) printf("%d ", a[q[hh]]);
} - 对于最大值问题,维护一个单调递减队列:队列头部是当前窗口的最大值,新元素入队时,删除队列中所有比它小的元素,以保持队列单调递减。
hh = 0, tt = -1;
for (int i = 0; i < n; i++)
{
if (hh <= tt && i - k + 1 > q[hh]) hh++;
//队列不为空且队尾元素小于等于 x 时,弹出队尾元素(使队列具有单调性)
while (hh <= tt && a[q[tt]] <= a[i]) tt--;
//当前元素下标 i 入队
q[++tt] = i;
if (i >= k - 1) printf("%d ", a[q[hh]]);
}
完整代码
|
时间和空间复杂度
时间复杂度:O(n)
空间复杂度:O(n)
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 ZW_Blog!