Sliding Window(滑动窗口)
Posted 鄉勇
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Sliding Window(滑动窗口)相关的知识,希望对你有一定的参考价值。
Time Limit: 12000MS | Memory Limit: 65536K | |
Total Submissions: 58002 | Accepted: 16616 | |
Case Time Limit: 5000MS |
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
Output
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
Source
题目描述
现在有一堆数字共N个数字(N<=10^6),以及一个大小为k的窗口。现在这个从左边开始向右滑动,每次滑动一个单位,求出每次滑动后窗口中的最大值和最小值。
例如:
The array is [1 3 -1 -3 5 3 6 7], and k = 3.
输入输出格式
输入格式:
输入一共有两行,第一行为n,k。
第二行为n个数(<INT_MAX).
输出格式:
输出共两行,第一行为每次窗口滑动的最小值
第二行为每次窗口滑动的最大值
输入输出样例
8 3 1 3 -1 -3 5 3 6 7
-1 -3 -3 -3 3 3 3 3 5 5 6 7
说明
50%的数据,n<=10^5
100%的数据,n<=10^6
思路:单调队列。
分别维护一个单调上升队列和一个单调下降队列即可。
拿区间最大值来说吧,一个上升队列,它的队首值就是区间最大值。
如果窗口向后滑动,首先,在满足队列单调的前提下,把新值加入(不一定真的加入)。
如果队首值等于要去掉的值,队首后移。
代码实现:
1 #include<cstdio> 2 #define maxn 1000010 3 int n,k,s[maxn]; 4 int a; 5 int h1,t1,q1[maxn],a1[maxn],l1; 6 int h2,t2,q2[maxn],a2[maxn],l2; 7 int main(){ 8 scanf("%d%d",&n,&k); 9 for(int i=1;i<=n;i++){ 10 scanf("%d",&s[i]); 11 a=h1-1;h1=t1; 12 for(int j=a;j>=t1;j--) if(s[i]>=q1[j]){h1=j+1;break;} 13 q1[h1++]=s[i]; 14 if(i>k&&s[i-k]==q1[t1]) t1++;//因为判断先后的问题,一直RE一个点。 15 if(i>=k) a1[l1++]=q1[t1]; 16 a=h2-1;h2=t2; 17 for(int j=a;j>=t2;j--) if(s[i]<=q2[j]){h2=j+1;break;} 18 q2[h2++]=s[i]; 19 if(i>k&&s[i-k]==q2[t2]) t2++; 20 if(i>=k) a2[l2++]=q2[t2]; 21 } 22 for(int i=0;i<l1;i++) printf("%d ",a1[i]);putchar(‘\n‘); 23 for(int i=0;i<l2;i++) printf("%d ",a2[i]);putchar(‘\n‘); 24 return 0; 25 }
另一种写法(更工整些):
1 #include<cstdio> 2 #define maxn 1000010 3 int n,k,s[maxn]; 4 int a; 5 int h1,t1,q1[maxn],a1[maxn],l1; 6 int h2,t2,q2[maxn],a2[maxn],l2; 7 int main(){ 8 scanf("%d%d",&n,&k); 9 for(int i=1;i<=n;i++){ 10 scanf("%d",&s[i]); 11 q1[h1++]=1000000000;q2[h2++]=-1000000000; 12 for(int j=t1;j<h1;j++) 13 if(s[i]<q1[j]){q1[j]=s[i];h1=j+1;break;} 14 if(i>k&&s[i-k]==q1[t1]) t1++; 15 if(i>=k) a1[l1++]=q1[t1]; 16 for(int j=t2;j<h2;j++) 17 if(s[i]>q2[j]){q2[j]=s[i];h2=j+1;break;} 18 if(i>k&&s[i-k]==q2[t2]) t2++; 19 if(i>=k) a2[l2++]=q2[t2]; 20 } 21 for(int i=0;i<l1;i++) printf("%d ",a1[i]);putchar(‘\n‘); 22 for(int i=0;i<l2;i++) printf("%d ",a2[i]);putchar(‘\n‘); 23 return 0; 24 }
也可以分开写:
1 #include<cstdio> 2 #define maxn 1000010 3 int n,k,a,h,t; 4 int s[maxn],q[maxn]; 5 int main(){ 6 scanf("%d%d",&n,&k); 7 for(int i=1;i<=n;i++){ 8 scanf("%d",&s[i]); 9 q[h++]=1000000000; 10 for(int j=t;j<h;j++) if(s[i]<q[j]){q[j]=s[i];h=j+1;break;} 11 if(i>k&&s[i-k]==q[t]) t++; 12 if(i>=k) printf("%d ",q[t]); 13 } 14 putchar(‘\n‘);h=t=0; 15 for(int i=1;i<=n;i++){ 16 q[h++]=-1000000000; 17 for(int j=t;j<h;j++) if(s[i]>q[j]){q[j]=s[i];h=j+1;break;} 18 if(i>k&&s[i-k]==q[t]) t++; 19 if(i>=k) printf("%d ",q[t]); 20 } 21 putchar(‘\n‘); 22 return 0; 23 }
越来越短。
最后被poj接受的代码(2266mm):
1 #include<cstdio> 2 #define maxn 1000010 3 int n,k,s[maxn]; 4 int a; 5 int h1,t1,q1[maxn],a1[maxn],l1; 6 int h2,t2,q2[maxn],a2[maxn],l2; 7 inline int abs(int x){return x<0?-x:x;} 8 void write(int x){ 9 if(x) write(x/10); 10 else return; 11 putchar(x%10+‘0‘); 12 } 13 int main(){ 14 scanf("%d%d",&n,&k); 15 for(int i=1;i<=n;i++){ 16 scanf("%d",&s[i]); 17 a=h1-1;h1=t1; 18 for(int j=a;j>=t1;j--) if(s[i]>=q1[j]){h1=j+1;break;} 19 q1[h1++]=s[i]; 20 if(i>k&&s[i-k]==q1[t1]) t1++; 21 if(i>=k) a1[l1++]=q1[t1]; 22 a=h2-1;h2=t2; 23 for(int j=a;j>=t2;j--) if(s[i]<=q2[j]){h2=j+1;break;} 24 q2[h2++]=s[i]; 25 if(i>k&&s[i-k]==q2[t2]) t2++; 26 if(i>=k) a2[l2++]=q2[t2]; 27 } 28 for(int i=0;i<l1;i++){ 29 if(a1[i]<0) putchar(‘-‘); 30 write(abs(a1[i])); 31 if(!a1[i]) putchar(‘0‘); 32 if(i<l1-1) putchar(‘ ‘); 33 } 34 putchar(‘\n‘); 35 for(int i=0;i<l2;i++){ 36 if(a2[i]<0) putchar(‘-‘); 37 write(abs(a2[i])); 38 if(!a2[i]) putchar(‘0‘); 39 if(i<l2-1) putchar(‘ ‘); 40 } 41 putchar(‘\n‘); 42 return 0; 43 }
题目来源:POJ,洛谷
以上是关于Sliding Window(滑动窗口)的主要内容,如果未能解决你的问题,请参考以下文章
POJ - 2823 Sliding Window (滑动窗口入门)
LeetCode 239. Sliding Window Maximum(滑动窗口最大值)