首页 > 代码库 > 【编程题目】栈的 push、pop 序列

【编程题目】栈的 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:15end time = 17:20 */#include <stdio.h>int * getlocation(int data, int * poplist, int len){    for(int i = 0; i < len; i++)    {        if(data =http://www.mamicode.com/= 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;}

 

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