前言
你好啊,我最近在学acwing的算法基础课,备战蓝桥杯,如果你也是一样的话,欢迎一起学习交流~
一、题目&解读
1、题目
二、思路
1、滑动窗口最大值
以滑动窗口最大值为例,如下图
图的链接
注意i=4
的时候,此时a[4]=9
所以是先清空队列,再将9
入队
2、代码实现
每个元素进队和出队各一次 因此,时间复杂度 O(n)
int head = 0, tail = -1;
for (int i = 0; i < n;++i) {
//判断队列是否为空 //判断队头是否已经滑出窗口
if (head<=tail && i - k + 1 > q[head])
head++;//如果满足 则出队
while (head<=tail&&a[q[tail]]>=a[i])tail --;
// 若队尾不单调,弹出队尾 //a[q[tail]]:队尾的值
q[++ tail] = i;//入队 存储当前元素的下标值
if (i >= k - 1)//保证窗口内元素为k个时 输出队头
printf("%d ", a[q[head]]);
}
puts("");
3、模板
常见模型:找出滑动窗口中的最大值/最小值
int hh = 0, tt = -1;
for (int i = 0; i < n; i ++ )
{
while (hh <= tt && check_out(q[hh])) hh ++ ; // 判断队头是否滑出窗口
while (hh <= tt && check(q[tt], i)) tt -- ;
q[ ++ tt] = i;
}
三、AC代码
#include <iostream>
using namespace std;
const int N = 1000010;//注意数据范围 否则会Segmentation Fault
int a[N], q[N];//q[N]存的是窗口元素的下标值,用于判断队头出队
int main ( ) {
int n, k;
scanf("%d%d", &n, &k);
for (int i = 0; i < n;i++)
scanf("%d", &a[i]);
int head = 0, tail = -1;
for (int i = 0; i < n;++i) {
//判断队列是否为空 //判断队头是否已经滑出窗口
if (head<=tail && i - k + 1 > q[head])
head++;//如果满足 则出队
while (head<=tail&&a[q[tail]]>=a[i])// 若队尾不单调,tt减1
tail--; //a[q[tail]]:队尾的值
q[++ tail] = i;
if (i >= k - 1)//保证窗口内元素为k个时 输出队头
printf("%d ", a[q[head]]);
}
puts("");
head = 0, tail = -1;
for (int i = 0; i < n;++i) {
//判断队列是否为空 //判断队头是否已经滑出窗口
if (head<=tail && i - k + 1 > q[head])
head++;
while (head<=tail&&a[q[tail]]<=a[i])
tail--;
q[++ tail] = i;
if (i >= k - 1)
printf("%d ", a[q[head]]);
}
puts("");
return 0;
}
四、总结
学数据结构 最主要的还是要画图,先画一遍,代码自然就能够写了。
结尾:
感谢你能看完,希望对你有帮助 ,如有错误欢迎指正,码字不易,给个赞呗