滑动窗口详解

目录

1:滑动窗口解释

2:滑动窗口例题


1:滑动窗口解释

滑动窗口在算法中应该也算常见,怎么说呢,就是加入给你一个整型数组,再给你设定个值作为区间,每次在这个区间中寻找你所需要的值,区间继续滑动,知道无法滑动,即有区间到达了数组终点。具体举个例子来说哈

给你一个整型数组:1  3  -1  -3  5  3  6  7

再给你一个区间值k=3(假如我们想要求的是最小值)

意思就是呢一开始的区间是 1  3  -1   它的最小值=-1

继续  ,区间变为3  -1  -3   它的最小值= -3

继续,  区间变为-1  -3  5  它的最小值=  -3

继续  , 区间变为-3  5  3  它的最小值=  -3

继续 ,区间变为5  3   6    它的最小值=   3

继续 ,区间变为  3  6  7  它的最小值 =  3

也就是最后的输出是: -1   -3   -3  -3  3   3

这不很类似一个滑动的窗口设定了一个固定的区间让我们在这个区间中取我们需要的值嘛!!!

那按照这样子的解释,滑动窗口,是不是也类似于可以用双指针来做,当然太深奥也不好理解(其实我不会,嘿嘿),我们就用头尾指针来说说,我们一开始将头指针就设置为数组起点,尾指针设置为滑动窗口的区间终点,然后我们开始在这个窗口中寻找所需要的值,接着开始更新窗口端点,也就是将头尾指针各自更新,也就是都加1。以此类推。说了大家也不好理解,看下代码吧!!!

  这里我求的是最小值的!!!!!!

#include
using namespace std;
int a[100];
int n,k;
int main()
{
	cin>>n>>k;//分别是数组的大小和区间的限制数
	for(int i=1;i<=n;i++){
		cin>>a[i];
	}
	int h=1;//头指针
	int t=h+k-1;//尾指针
	for(int i=1;i<=n;i++){//其实也可以不用循环到n的,n-k+1,其实就行,毕竟区间限制数不给它继续循环到n
		int ma=a[h];//作为做小值标量,遇到更小的就换
		for(int j=h;j<=t;j++){
			if(a[j]n)break;//如果位置指针超过数组终点要跳出循环
	}
	return 0;
}

 

滑动窗口详解_第1张图片

当然了这样子的代码答案肯定是对的,但是会超时,一些不严格的题目会过,但是一般的都不会过的,所有我们应该再想想别的办法来优化这个算法,方法不变,还是用到头尾指针的办法。不知道大家知不知道单调队列,队列是头进尾出,但是单调队列头尾都可以,并且是单调的递增或者单调递减的。

还是刚刚举的例子:

数组是  1  3  -1  -3  5  3  6  7

k=3

这时候我们还需要再开一个数组用来储存它的位置p[100]

一个一个放,首先是1入队,接着3入队,3>1可以入队,现在是{1,3},接着-1,因为-1很明显小于前两个,他一入队,前面两个根本就没机会成为最小值,所有,前面两个出队,他入队,现在是{-1},继续是-3,-3<-1,那么-1就没机会了。-1出队,-3进队。{-3},接着·是5,5>-3,入队,现在是{-3,5},然后是3,3<5,那么5就没机会了,5出队,现在是{-3,3},接着是6,6大于他们,入队,现在是{-3,3,6},继续是7,7大于他们应该也要入队,但要注意区间限制值是3,所以,尾巴要出去了,现在则是{3,6,7}

这就是大致的思想了!!!!!(注意啊,这里我用的单调队列是单调递增的,所有每次输出的都是尾部位置的值,也就是那个区间的最小值了)

接下来就是用代码来具体看看这个题目了

#include
using namespace std;
int a[100];
int p[100];
int n,k;
int main()
{
	cin>>n>>k;
	for(int i=1;i<=n;i++){
		cin>>a[i];
		p[i]=i;//位置全部初始化
	}
	//求最小值
	int h=1;//头指针
	int t=0;//尾指针
	
	for(int i=1;i<=n;i++){
		while(h<=t&&p[h]+k<=i)h++;
		while(h<=t&&a[i]=k)cout<

滑动窗口详解_第2张图片

 2:滑动窗口例题

题目描述:

有一个长为 nn 的序列 aa,以及一个大小为 kk 的窗口。现在这个从左边开始向右滑动,每次滑动一个单位,求出每次滑动后窗口中的最大值和最小值。

例如:

The array is [1,3,-1,-3,5,3,6,7][1,3,−1,−3,5,3,6,7], and k = 3k=3。

滑动窗口详解_第3张图片

输入格式

输入一共有两行,第一行有两个正整数 n,kn,k。 第二行 nn 个整数,表示序列 aa

输出格式

输出共两行,第一行为每次窗口滑动的最小值
第二行为每次窗口滑动的最大值

输入输出样例

输入 #1复制

8 3
1 3 -1 -3 5 3 6 7

输出 #1复制

-1 -3 -3 -3 3 3
3 3 5 5 6 7

说明/提示

【数据范围】
对于 50\%50% 的数据,1 \le n \le 10^51≤n≤105;
对于 100\%100% 的数据,1\le k \le n \le 10^61≤k≤n≤106,a_i \in [-2^{31},2^{31})ai​∈[−231,231)。

 

#include
using namespace std;
int n,m;
int q1[1000001],q2[1000001];
int a[1000001];
int min_deque()
{
    int h=1,t=0;
    for(int i=1;i<=n;i++)
    {
        while(h<=t&&q1[h]+m<=i) h++;
        while(h<=t&&a[i]=m) cout<a[q2[t]]) t--;
        q2[++t]=i;
        if(i>=m) cout<>n>>m;
    for(int i=1;i<=n;i++) cin>>a[i];
    min_deque();
    max_deque();
    return 0;
}

你可能感兴趣的:(算法,算法,c++,蓝桥杯)