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

来源:互联网 发布:ubuntu 解压缩 编辑:程序博客网 时间:2024/05/22 02:22

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 scanfconst 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 scanfconst 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);}
原创粉丝点击