滑动窗口

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的上下滑动,我怎么做?

选项卡执行android中下一个片段中存在的代码

华为OD机试 -滑动窗口最大和(Java) | 机试题+算法思路+考点+代码解析 2023

华为OD机试 -滑动窗口最大和(Java) | 机试题+算法思路+考点+代码解析 2023