Sliding Window
Time Limit:12000MS Memory Limit:65536KB 64bit IO Format:%I64d & %I64u
Description
An array of size n ≤ 10 6 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.
Input
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.
Output
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.
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題意 : 给定一个数字序列,与每次所能看见的序列长度m即窗户长度,从左向右依次移动窗户,输出每次所能看到的序列长度的最大值与最小值,直到序列结束.思路: 以求最小值为例, 1.构造递增的单调队列,即队尾元素需要小于当前元素,否则队尾元素出队. 2.首先,将前 m-1 个元素按照单调队列原则进队,并记录队列中的每个元素在数组中的下标; 其次,将剩余的元素依次进队,以 第i元素为例子,将第i元素与队尾比较,若是小于队尾,则队尾出队,否则当前元素进队,此时队列是单调递增有序的, 再之,将队头元素的下标与当前元素的下标比较,若 当前元素下标 - 队头元素下标<=m-1,则队头元素便为最小值,否则队头出队. 3.将剩余元素依次进行步骤2,便得到所求的所有最小值,求最大值亦然.AC代码分析 (请用C++提交,否则Time Limit Exceeded):
1 #include <iostream> 2 #include <stdio.h> 3 #include <cstring> 4 #include <algorithm> 5 #include <cmath> 6 #include <vector> 7 #include <map> 8 #include<string.h> 9 #include<stack> 10 #include<set> 11 #include <queue> 12 using namespace std; 13 int a[1000005]; 14 //队列中各元素的下标 15 int p[1000005]; 16 //各个区间的最大值 17 int max1[1000005]; 18 //各个区间的最小值 19 int min1[1000005]; 20 //数组模拟递增队列 21 int qmax[1000005]; 22 //数组模拟递减队列 23 int qmin[1000005]; 24 //队头,队尾 25 int head,tail; 26 int main() 27 { 28 int n,m,i,t; 29 while(~scanf("%d%d",&n,&m)) 30 { 31 for( i = 1; i<=n; i++) scanf("%d",a+i); 32 //队头队尾初始化 33 head = 1; 34 tail = 0; 35 t = 1; 36 //前m-1个元素进队列 37 for( i = 1; i<=m-1; i++) 38 { 39 while(head<=tail&&qmin[tail]>=a[i]) tail--; 40 qmin[++tail] = a[i]; 41 //队列中各元素的下标 42 p[tail] = i; 43 44 } 45 //求所有的最小值 46 for(; i<=n; i++) 47 { 48 //进队 49 while(head<=tail&&qmin[tail]>=a[i]) tail--; 50 qmin[++tail] = a[i]; 51 p[tail] = i; 52 //判断对头是否在当前范围内 53 while(i-p[head]>m-1) 54 head++; 55 min1[t++] = qmin[head]; 56 } 57 head = 1; 58 tail = 0; 59 t = 1; 60 //求所有的最大值 61 for( i = 1; i<=m-1; i++) 62 { 63 while(head<=tail&&qmax[tail]<=a[i]) tail--; 64 qmax[++tail] = a[i]; 65 p[tail] = i; 66 } 67 for(; i<=n; i++) 68 { 69 //进队 70 while(head<=tail&&qmax[tail]<=a[i]) tail--; 71 qmax[++tail] = a[i]; 72 p[tail] = i; 73 //判断对头是否在当前范围内 74 while(i-p[head]>m-1) 75 head++; 76 max1[t++] = qmax[head]; 77 } 78 for( i = 1; i<t; i++) 79 { 80 if(i == 1) 81 printf("%d",min1[i]); 82 else 83 printf(" %d",min1[i]); 84 } 85 printf("\n"); 86 for( i = 1; i<t; i++) 87 { 88 if(i == 1) 89 printf("%d",max1[i]); 90 else 91 printf(" %d",max1[i]); 92 } 93 94 } 95 return 0; 96 }
本文为个人随笔,如有不当之处,望各位大佬多多指教.若能为各位博友提供小小帮助,不胜荣幸.