判断栈输出序列的合法性(模拟法)

来源:互联网 发布:linux 串口驱动 编辑:程序博客网 时间:2024/05/18 11:49

问题描述:对于N个元素(1到N)。给定两个N的全排序列S1,S2。其中S1为入栈顺序,是2为出栈顺序。问:对于S1的入栈顺序,能否经过若干的出入栈操作,使得出栈顺序恰为S2。是输出YES,否输出NO。

思路:由于只有一个栈,很容易得出S1到S2的操作序列是唯一的,因此可以用模拟法。遍历S2的每个元素。

for(遍历S2的每一个元素)

{

    if(当前元素还没有入栈)

        将其入栈(有可能压入多个数,但最后压入的一定是当前元素,)再将它出栈

   if(当前元素在栈中)

      {

         是否为栈顶:是则出栈,否则错误,无法满足条件,退出循环;

      }

}

但是这样的思路在实现上还是有些复杂,如判断在哪里的步骤要遍历数组,不仅增加复杂度,还影响到代码的编写,因此先做一下变换,“固定”输入顺序。

一建立映射,简化问题:

由于输入,输出序列的都是不确定的状态,因此给问题的解决带来一定的难度,此时我们发现N个元素恰为1到N,可以通过一个映射关系“固定”某一个序列,很自然的想到“元素---位置”这一映射,这样可以把输入序列变为S0(1,2,3...N),此时输出序列变为S2.那么这一映射又是怎样实现的呢?其实,还是非常简单的。举一个例子:(为了区别,元素采用中文,位置用数字表示,一共有6个元素)

要解决的问题:

输入顺序:五,三,二,一,六,四。

输出顺序:三,六,二,四,五,一。

对于映射后的输入顺序已经是固定了,即是1,2,3,4,5,6。那么输出顺序应该变为什么呢?此时,在输入顺序:三是第2个元素,六是第5个元素,二是第3个元素。。。所以输出顺序应该是2,5,3,6,1,4。代表要输出顺序依次为:(按输入顺序)第2个元素,也就是三,第5个元素,也就是六。。。代码实现如下:

for(i=1;i<=n;i++){
    for(j=1;j<=n;j++){        if(s2[i]==s1[i]){
            a[i]=j;break;
        }   }}

此时a[]数组也是N的一个全排序。

此时,问题就变为从S0(1,2,3,...N)到a[]的一个操作。

入栈顺序从小到大,用min表示还没有入栈元素的最小值,表示min~N这些数还没有入栈。。。按照上面的思路代码如下:

min=1;res=true;for(i=1;i<=n;i++){x=a[i];if(x>=min){for(j=min;j<=x;j++)//把min~x这几个元素入栈s.push(j);s.pop();//将X出栈min=x+1;//此时还没有入栈的是X+1~N这些数}else{if(s.top()!=x){res=false;break;}elses.pop();}}if(res)printf("Yes\n");elseprintf("No\n");