Sliding Window滑动窗口 POJ - 2823
目录
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.
向您提供大小为 n ≤ 106的阵列。有一个大小k的滑动窗口,从阵列的左侧移动到最右侧。您只能在窗口中看到k数字。每次滑动窗口向右移动一个位置。下面是一个例子:
阵列是[1 3 -1 -3 5 3 6 7], k是 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.
您的任务是确定每个位置滑动窗口中的最大值和最小值。
Input
Sample Input
8 3
1 3 -1 -3 5 3 6 7
Sample Output
-1 -3 -3 -3 3 3
3 3 5 5 6 7
题意描述:
给定窗户总长度和可滑动窗口长度,确定每个位置滑动窗口中的最大值和最小值。
解题思路:
利用单调栈,维持队列使其是一个递减的队列,使最大值始终在队首。将n个数存入数组中,从头遍历数组。当队列中有值时,将队尾元素与此时遍历到的数组的元素a[i]比较;如果队尾元素≤a[i],队尾元素出队,继续比较现在的队尾元素和a[i]大小,直至队尾元素>a[i]或者队列中没有元素,a[i]从队尾入队.......一边遍历数组的元素使其入队,一边判断此时队首的最大值是否属于此时的滑动窗口,不属于的话,就将队首元素出队,继续判断,直至找到属于的此滑动窗口的队首元素,保存此元素为此时滑动窗口的最大值。最小同理。
AC代码:
#include<stdio.h>
#include<queue>
#include<deque>//双向队列
using namespace std;
int n,m,l,r;
int a[1000005],b[1000005];
int main()
{
scanf("%d%d",&n,&m);
l=0,r=-1;
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
for(int i=1;i<=n;i++)//单调递减
{
while(l<=r&&a[i]<=a[b[r]])
{
r--;//如果进入新的值不递减,那么一直退栈直到递减
}
b[++r]=i;
while(i-b[l]>=m)
{
l++;
}
if(i>=m)
printf("%d ",a[b[l]]);
}
printf("\n");
l=0,r=-1;
for(int i=1;i<=n;i++)//单调递增
{
while(l<=r&&a[i]>a[b[r]]) r--; //如果进入新的值不递增,那么一直退栈直到递增
b[++r]=i;
while(i-b[l]>=m) l++;
if(i>=m) printf("%d ",a[b[l]]);
}
printf("\n");
return 0;
}