Sliding Window(滑动窗口)

Sliding Window
题目描述

An array of size n ≤ 106 is given to you. There is a sliding window of size k which is moving from the very left of the array to the very right. You can only see the k numbers in the window. Each time the sliding window moves rightwards by one position. Following is an example:
The array is [1 3 -1 -3 5 3 6 7], and k is 3.
Window position Minimum value Maximum value

[1 3 -1] -3 5 3 6 7 -1 3

1 [3 -1 -3] 5 3 6 7 -3 3

1 3 [-1 -3 5] 3 6 7 -3 5

1 3 -1 [-3 5 3] 6 7 -3 5

1 3 -1 -3 [5 3 6] 7 3 6

1 3 -1 -3 5 [3 6 7] 3 7

Your task is to determine the maximum and minimum values in the sliding window at each position.

输入描述:
The input consists of two lines. The first line contains two integers n and k which are the lengths of the array and the sliding window. There are n integers in the second line.
输出描述:
There are two lines in the output. The first line gives the minimum values in the window at each position, from left to right, respectively. The second line gives the maximum values.
示例1
输入
复制
8 3
1 3 -1 -3 5 3 6 7
输出
复制
-1 -3 -3 -3 3 3
3 3 5 5 6 7

思路:题目让我们每次在长度为k的区间内输出区间最小值,一眼就可以看出来这道题是滑动窗口的模板题,我们可以用一个双端队列来维护这个长度为k的滑动窗口,然后我们让这个窗口每次移动一下,在移动的过程中维护窗口的最大值或者最小值(维护的答案就在队列的头部)。重点是如何来维护这个队列。
首先,当这个窗口要向后滑动时,我们要将队头删除:

if(!q1.empty()&&q.front()+k-1<i)//队列不空且队列右端点小于i(i是从0开始的)的值
	q1.pop_front();

那么我们如何维护窗口头部是最小值呢?当存在我们的尾部比要进来的元素大时,这个时候就需要删除尾部的元素,这样做的目的是让窗口内的最小值走到窗口的头部:

while(!q1.empty()&&a[i]<a[q1.back()])//当队列不空且当前值小于队尾值
	q1.pop_back();

最后当存在我们维护的窗口达到k时,输出数据。
Accode:

#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>

using namespace std;

const int N = 1e6+5;
int a[N];

void minx(int n,int k)
{
    
    
    deque<int>q1;
    for(int i=0;i<n;i++)
    {
    
    
        while(!q1.empty()&&a[i]<a[q1.back()])
            q1.pop_back();
        if(!q1.empty()&&q1.front()+k-1<i)//更新窗口区间的最小值
            q1.pop_front();
        q1.push_back(i);//将下标入队
        if(i+1>=k)cout<<a[q1.front()]<<' ';
    }
}

void maxx(int n,int k)
{
    
    
    deque<int>q2;
    for(int i=0;i<n;i++)
    {
    
    
        while(!q2.empty()&&a[i]>a[q2.back()])
            q2.pop_back();
        if(!q2.empty()&&q2.front()+k-1<i)//更新窗口区间的最大值
            q2.pop_front();
        q2.push_back(i);
        if(i+1>=k)cout<<a[q2.front()]<<' ';
    }

}

int main()
{
    
    
    int n,k;
    cin>>n>>k;
    for(int i=0;i<n;i++)cin>>a[i];
    minx(n,k);
    cout<<endl;
    maxx(n,k);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Stephen_Curry___/article/details/126733611