滑动窗口
Posted hhyx
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了滑动窗口相关的知识,希望对你有一定的参考价值。
# 题意
长度为n的序列,只能看到长度为k的滑动窗口,从数组的最左边移动到最右边,
求出每个滑动窗口的最大值和最小值
# 题解
长度为n的序列,每次从输出k个连续的数中的最大值和最小值
暴力做法,对每一段i,i…i+k-1 逐个进行比较得最大值,时间复杂度为O(n*k),
数据范围大就会超时
优化:
单调队列中存的是下标,用来判断是不是超过区间限定长度
当求窗口中的最小值时,
如果队列中存在两个元素,满足 a[i] >= a[j] 且 i < j,那么无论在什么时候我们都不会取 a[i] 作为最小值了,所以可以直接将 a[i] 删掉;
此时队列中剩下的元素严格单调递增,所以队头就是整个队列中的最小值,可以用 O(1)的时间找到;
为了维护队列的这个性质,我们在往队尾插入元素之前,先将队尾大于等于当前数的元素全部弹出即可;
这样所有数均只进队一次,出队一次,所以时间复杂度是 O(n)的
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=1e5+10; 4 int n,k; 5 int a[N]; 6 int que[N],tt,hh=1; 7 int main(){ 8 cin>>n>>k; 9 for(int i=1;i<=n;i++) 10 cin>>a[i]; 11 for(int i=1;i<=n;i++){ 12 if(hh<=tt && i-k+1>que[hh]) hh++; 13 while(hh<=tt && a[que[tt]]>=a[i]) tt--; 14 que[++tt]=i; 15 if(i-k+1>0) 16 cout<<a[que[hh]]<<‘ ‘; 17 } 18 cout<<endl; 19 hh=1,tt=0; 20 for(int i=1;i<=n;i++){ 21 if(hh<=tt && i-k+1>que[hh]) hh++; 22 while(hh<=tt && a[que[hh]]<=a[i]) tt--; 23 que[++tt]=i; 24 if(i-k+1>0) 25 cout<<a[que[hh]]<<‘ ‘; 26 } 27 cout<<endl; 28 }
以上是关于滑动窗口的主要内容,如果未能解决你的问题,请参考以下文章
我的片段中有 webview,当滑动 webview 时, viewPager 也开始滑动
在一个片段中检测Recyclerview的上下滑动,我怎么做?