注释版
#include<iostream>
using namespace std;
const int N = 1e6 + 10;
int n, k, q[N], a[N];//q[N]存的是数组下标
int main()
{
int tt = -1, hh=0;//hh队列头 tt队列尾
cin.tie(0);
ios::sync_with_stdio(false);
cin>>n>>k;
for(int i = 0; i <n; i ++) cin>>a[i];
for(int i = 0; i < n; i ++)
{
//维持滑动窗口的大小
//当队列不为空(hh <= tt) 且 当当前滑动窗口的大小(i - q[hh] + 1)>我们设定的
//滑动窗口的大小(k),队列弹出队列头元素以维持滑动窗口的大小
if(hh <= tt && k < i - q[hh] + 1) hh ++;
//构造单调递增队列
//当队列不为空(hh <= tt) 且 当队列队尾元素>=当前元素(a[i])时,那么队尾元素
//就一定不是当前窗口最小值,删去队尾元素,加入当前元素(q[ ++ tt] = i)
while(hh <= tt && a[q[tt]] >= a[i]) tt --;
q[ ++ tt] = i;
if(i + 1 >= k) printf("%d ", a[q[hh]]);
}
puts("");
hh = 0,tt = -1;
for(int i = 0; i < n; i ++)
{
if(hh <= tt && k < i - q[hh] + 1) hh ++;
while(hh <= tt && a[q[tt]] <= a[i]) tt --;
q[ ++ tt] = i;
if(i + 1 >= k ) printf("%d ", a[q[hh]]);
}
return 0;
}
无注释版
#include<iostream>
using namespace std;
int h,t=-1;
const int N=1e6+10;
int a[N],q[N];
int main()
{
int n,k;
cin>>n>>k;
for(int i=0;i<n;i++) cin>>a[i];
for(int i=0;i<n;i++)
{
if(h<=t && i-q[h]+1>k) h++;
while(h<=t && a[q[t]]>=a[i]) t--;
q[++t]=i;
if(i+1>=k) cout<<a[q[h]]<<' ';
}
cout<<endl;
h=0;t=-1;
for(int i=0;i<n;i++)
{
if(h<=t && i-q[h]+1>k) h++;
while(h<=t && a[q[t]]<=a[i]) t--;
q[++t]=i;
if(i+1>=k) cout<<a[q[h]]<<' ';
}
return 0;
}
无注释版2
#include<iostream>
using namespace std;
const int N=1e6+10;
int que[N],head,tail,a[N];
int main()
{
int n,k;
cin>>n>>k;
for(int i=0;i<n;i++) cin>>a[i];
for(int i=0;i<n;i++)
{
if(tail-head>0 && i-que[head]+1>k) head++;
while(tail-head>0 && a[que[tail-1]]>=a[i]) tail--;
que[tail++]=i;
if(i>=k-1) cout<<a[que[head]]<<' ';
}
cout<<endl;
tail=head=0;
for(int i=0;i<n;i++)
{
if(tail-head>0 && i-que[head]+1>k) head++;
while(tail-head>0 && a[que[tail-1]]<=a[i]) tail--;
que[tail++]=i;
if(i>=k-1) cout<<a[que[head]]<<' ';
}
}
有两重循环 为什么时间复杂度是O(N)的?
时间复杂度一般省略常数
时间复杂度确实是2n但一般说它是n
时间复杂度一般省略常数
时间复杂度确实是2n但一般说它是n
时间复杂度一般省略常数
时间复杂度确实是2n但一般说它是n
两重循环不应该是n^2吗
这也不是嵌套的啊
最坏情况下,两重循环一共入队n次,出队n次加在一起2n次
疑问? q存的都是下标这我清楚,但是每次i循环之后,q中的结果代表的是什么呢 即每次的q中的结果是什么意思呢?
i减k加1 > q(hh) 怎么理解呀
从0开始
如果i为2 那不就是0大于0吗
好困扰
写的是i>=k-1(0大于等于0),所以i==2时,会输出
不应该是一个单调递增 一个单调递减队列嘛
所以hh和tt随在左边,实在分不清了
head左 tail 右
赞👍
大佬,我想问一下,就是虽然说是叫单调队列,但是这个tt–,是不是不符合队列的先进先出的性质,
类似于双端队列deque
谢
nb,就喜欢你这种直白好懂的。某些题解文字装可爱,指代含糊不清,搞得人云里雾里,根本没耐心看。
解释的真清楚
https://blog.csdn.net/m0_74215326/article/details/128835688?spm=1001.2014.3001.5502
注解写的好呀 ,饭都喂嘴边了
有一个低级问题,为什么hh<=tt时队列不为空?
因为一开始 hh=0, tt=-1; 而这个队列是通过 hh++ 和 tt– 各自进行队列头部出队 Or 队尾出队的。因此如果出现 hh==tt,那么表示当前肯定存在最后一个唯一值,而如果此时如果头部继续出队Or队尾继续出队,会导致 不满足 hh<==tt。(此时 hh>tt Or tt<hh)
大佬问个问题,hh=0,tt=-1,通过hh++,和t–操作,怎么会有hh<=tt这种情况呢?
呃呃仔细看题目; tt– 这个是在什么时候操作的; tt 是在什么时候操作的。
对于正常的队列入队Or出队操作。 入队 == tt, 出队== hh– 。; 而你这里的 tt– 是特指队尾收缩的情况(这个并不属于正常的 队列出队操作)。
tql 顶上去,看明白,谢谢大佬!!
这个注释写的真是好 tql
把这个题解顶上去!
清晰 明了 没有多余的废话
puts(“”)是换行的意思吗
对
写的确实是特别好,就第一份代码输入那一行少打了个空格,强迫症有点难受hh
写的真好
i从0开始看着好难受,但是从1开始又已知调试不正确,怎么破
从1开始的,注意i和队列的下标起点一致就行
哈哈谢谢,已经解决了
可以请教下为什么i和队列下标起点hh要一致呢?
注释相当不错,要注意的是q队列存下标
确实·