您的位置:首页 > 其它

POJ-2823--Sliding Window--双端队列实现单调队列

2017-08-04 15:36 507 查看
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

题意:给n个数和k,然后从前向后找出每挨着的三个数的最小值和最大值。

解题思路:双端队列来实现单调队列再好不过了,既能前进前出,又能后进后出。维护两个队列即可,一个单调递减的,一个单调递增的。

附上两个代码,第一个代码是自己手写的维护单调队列最初的代码,比较复杂。后来去了网上才看到,三行代码就能维护一个单调的队列。代码二为简化后的代码。

PS:此代码用C++交TLE,G++:代码1:5016ms。代码2:4922ms

代码1:

#include<iostream>
#include<queue>
#include<cstdio>
#include<deque>
#define sf scanf
const int M=1e6+10;
using namespace std;
struct node
{
int x;
int y;
} s[M+50];
void Min_Max(int n,int k)
{
int i;
deque<node>q;
for(i=1; i<=k; i++)//先输出前k的值当中最小值
{
if(q.empty()||s[i].x>=q.back().x)
q.push_back(s[i]);
else
{
while(s[i].x<q.back().x)
{
q.pop_back();
if(q.empty())
break;
}
q.push_back(s[i]);//维护单调递减队列
}
}
cout<<q.front().x;
for(i=k+1; i<=n; i++)
{
if(q.empty()||s[i].x>=q.back().x)
q.push_back(s[i]);
else
{
while(s[i].x<q.back().x)
{
q.pop_back();
if(q.empty())
break;
}
q.push_back(s[i]);
}
while(q.back().y-q.front().y>=k)//这里判断最后一个和前一个的下标差值是否小于k
q.pop_front();
cout<<" "<<q.front().x;//每次循环都要输出一个最小值
}
cout<<endl;
}
void Max_Min(int n,int k)
{
int i;
deque<node>q;
for(i=1; i<=k; i++)
{
if(q.empty()||s[i].x<=q.back().x)
q.push_back(s[i]);
else
{
while(s[i].x>q.back().x)
{
q.pop_back();
if(q.empty())
break;
}
q.push_back(s[i]);
}
}
cout<<q.front().x;
for(i=k+1; i<=n; i++)
{
if(q.empty()||s[i].x<=q.back().x)
q.push_back(s[i]);
else
{
while(s[i].x>q.back().x)
{
q.pop_back();
if(q.empty())
break;
}
q.push_back(s[i]);
}
while(q.back().y-q.front().y>=k)
q.pop_front();
cout<<" "<<q.front().x;
}
}
int main()
{
int n,k,i,j;
sf("%d%d",&n,&k);
for(i=1; i<=n; i++)
{
sf("%d",&s[i].x);
s[i].y=i;//将每个值的下标存入
}
Min_Max(n,k);//单调递减的队列
Max_Min(n,k);//单调递增的队列
}


简化后的代码2:

#include<iostream>
#include<queue>
#include<cstdio>
#include<deque>
#define sf scanf
const int M=1e6+10;
using namespace std;
struct node
{
int x;
int y;
} s[M+50];
void Min_Max(int n,int k)
{
int i;
deque<node>q;
for(i=1; i<=k; i++)
{
while(!q.empty() && s[i].x<q.back().x)
q.pop_back();
q.push_back(s[i]);
}
cout<<q.front().x;
for(i=k+1; i<=n; i++)
{
while(!q.empty() && s[i].x<q.back().x)
q.pop_back();
q.push_back(s[i]);
while(q.back().y-q.front().y>=k)
q.pop_front();
cout<<" "<<q.front().x;
}
cout<<endl;
}
void Max_Min(int n,int k)
{
int i;
deque<node>q;
for(i=1; i<=k; i++)
{
while(!q.empty() && s[i].x>q.back().x)
q.pop_back();
q.push_back(s[i]);
}
cout<<q.front().x;
for(i=k+1; i<=n; i++)
{
while(!q.empty() && s[i].x>q.back().x)
q.pop_back();
q.push_back(s[i]);
while(q.back().y-q.front().y>=k)
q.pop_front();
cout<<" "<<q.front().x;
}
}
int main()
{
int n,k,i,j;
sf("%d%d",&n,&k);
for(i=1; i<=n; i++)
{
sf("%d",&s[i].x);
s[i].y=i;
}
Min_Max(n,k);
Max_Min(n,k);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: