【编程题目】栈的 push、pop 序列

29.栈的 push、pop 序列(栈)
题目:输入两个整数序列。其中一个序列表示栈的 push 顺序,
判断另一个序列有没有可能是对应的 pop 顺序。
为了简单起见,我们假设 push 序列的任意两个整数都是不相等的。
比如输入的 push 序列是 1、2、3、4、5,那么 4、5、3、2、1 就有可能是一个 pop 系列。
因为可以有如下的 push 和 pop 序列:
push 1,push 2,push 3,push 4,pop,push 5,pop,pop,pop,pop,
这样得到的 pop 序列就是 4、5、3、2、1。
但序列 4、3、5、1、2 就不可能是 push 序列 1、2、3、4、5 的 pop 序列。

 

思路:

首先,我记录了每个pop序列中每一个元素对应在push序列中的位置。这就像是把push序列强制成0 1 2 3 4...一样,这样push序列就是从小到大排列的了。

然后,观察从小到大排列的push序列,其合理的pop序列的特点。

4 5 3 2 1

记录第1个数字 并查找递增的数字 这里是 4  5  他们是递增的。

3 4 2 1 5

3 4 5 递增的

发现只要这些数字符合递增规律,那么pop序列就是合理的。且这些序列就是新加入数字后开始弹出的值。

还是拿3 4 2 1 5举例

3 是在压入1 2 3后弹出的第一个值

4 是在压入4后弹出的第一个值

5 是在压入5后弹出的第一个值

4 2 1这个递减的序列表示,没有压入新值,一直在弹出。

即,有递增序列表示有压入新的值,递减序列表示一直弹出。因为push序列时递增的,故压入的新值只能越来越大。

 

对于4、3、5、1、2

4 5 2 显然不满足递增关系 即压入5后不能再压入2 不是合法的pop序列

 

注:我没法证明,不知道是不是所有的都符合这个规律。谁能举出反例吗?

/*
29.栈的 push、pop 序列(栈)
题目:输入两个整数序列。其中一个序列表示栈的 push 顺序,
判断另一个序列有没有可能是对应的 pop 顺序。
为了简单起见,我们假设 push 序列的任意两个整数都是不相等的。 
比如输入的 push 序列是 1、2、3、4、5,那么 4、5、3、2、1 就有可能是一个 pop 系列。
因为可以有如下的 push 和 pop 序列:
push 1,push 2,push 3,push 4,pop,push 5,pop,pop,pop,pop,
这样得到的 pop 序列就是 4、5、3、2、1。
但序列 4、3、5、1、2 就不可能是 push 序列 1、2、3、4、5 的 pop 序列。
start time = 16:15
end time = 17:20 
*/

#include <stdio.h>

int * getlocation(int data, int * poplist, int len)
{
    for(int i = 0; i < len; i++)
    {
        if(data == poplist[i])
            return poplist + i;
    }
    return NULL;
}
bool ispop(int * pushlist, int * poplist, int len)
{
    for(int i = 0; i < len; i++) //记录pop中的数字对应push中那个位置
    {
        int * loc = getlocation(pushlist[i], poplist, len);
        if(loc != NULL)
        {
            *loc = i;
        }
        else
        {
            printf("error:the two list have different member!");
        }
    }

    
    int IncreaseNum2 = poplist[0];
    int IncreaseNum1;
    for(int i = 1; i < len; i++)
    {
        if(poplist[i] > poplist[i - 1])
        {
            IncreaseNum1 = IncreaseNum2;
            IncreaseNum2 = poplist[i];
            if(IncreaseNum2 < IncreaseNum1)
                return false;
        }
    }
    return true;
}

int main()
{
    int a[5] = {1,2,3,4,5};
    int b[5] = {5,3,4,2,1};
    bool is = ispop(a, b, 5);
    return 0;
}

 

网上答案:网上的思路惊人的一致,都是直接的建一个栈来模拟这个过程。比我的思路来的要好,计算少,又好理解。

http://blog.sina.com.cn/s/blog_a46817ff01019vtd.html

 如果我们希望pop的数字正好是栈顶数字,直接pop出栈即可;如果希望pop的数字目前不在栈顶,我们就到push序列中还没有
 * 被push到栈里的数字中去搜索这个数字,并把在它之前的所有数字都push进栈。如果所有的数字都被push进栈仍然没有找到这
 * 个数字,表明该序列不可能是一个pop序列。

网上随便找了个代码,还没验证http://www.cnblogs.com/aLittleBitCool/archive/2011/03/05/1971689.html

//栈的push、pop序列

#include<iostream>
#include<stack>
const int SIZE=5;                  //定义长度
using namespace std;
bool judge(int Spush[],int Spop[]){
    stack<int> my_stack;
    int iPush=0,iPop=0;
    while(iPush<SIZE){                //当栈顶和pop相等时,将pop后的栈顶与pop之后的元素相比,直到不等
        cout<<"push "<<Spush[iPush]<<endl;         //测试
        my_stack.push(Spush[iPush]);
        while(!my_stack.empty()&&iPop!=5&&my_stack.top()==Spop[iPop]){  //小心数组越界
            cout<<"pop "<<Spop[iPop]<<endl;      //测试
            iPop++;
            my_stack.pop();
        }
        iPush++;
    }
    if(iPop==SIZE) return true;
    else return false;
}
int main(void){
    int Spush[SIZE],Spop[SIZE];
    for(int i=0;i<SIZE;i++)
        cin>>Spush[i];
    for(int i=0;i<SIZE;i++)
        cin>>Spop[i];
    if(judge(Spush,Spop)) cout<<"Yes"<<endl;
    else cout<<"No"<<endl;
    system("pause");
    return 0;
}

 

posted @ 2014-09-19 16:46  匡子语  阅读(2269)  评论(0编辑  收藏  举报