面试题 22,栈的压入,弹出序列

思路:边界情况是输入队列为空。我的想法是,弹出序列必然在原序列上是逐个移动的,例如:如果弹出的第一个为3,那么下一个可以为2,也可以为4。为2表示弹出3后,没有压栈,继续弹出,为4表示又压入4再将4弹出。无论弹出2还是弹出4,下一弹出的又必须是其相邻的。比如弹出2,下一步要么弹出4,要么弹出1;弹出4的话,下一步要么弹出2,要么弹出5。如果出现“跳跃”,也就是弹出的数字不是当前数字的相邻位,就说明该弹出序列不满足要求。

为此,我定义了一个符号序列flag[],其长度和压栈序列相同,凡是弹出的会被置为false,函数prev()返回压栈序列里前一个不是false的,next()返回压栈序列里后一个不是false的。

代码:

#include <stdio.h>

int prev(bool *flag, int pushLength, int current){
    do {
        current--;
        if(current < 0 || current >= pushLength)
            return -1;
    }while(flag[current] == false);
    return current;
}

int next(bool *flag, int pushLength, int current){
    do {
        current++;
        if(current < 0 || current >= pushLength)
            return -1;
    }while(flag[current] == false);
    return current;
}

bool IsPopOrder(const int* push, const int* pop, unsigned int pushLength, unsigned int popLength){
    if(popLength > pushLength)
        return false;
    if(pushLength == 0 || popLength == 0)
        return false;
        
    bool *flag = new bool[pushLength];
    int i = 0;
    for(i = 0;i < pushLength;i++){
        flag[i] = true;
    }
    int current = -1;
    for(i = 0;i < pushLength; i++){
        if(push[i] == pop[0]){
            current = i;
        }
    }
    if(current == -1)
        return false;

    for(int i = 1;i < popLength;i++){
        flag[current] = false;
        int temp = current;
        int prevIte = prev(flag, pushLength, current);
        int nextIte = next(flag, pushLength, current);
        
        if(prevIte != -1 && push[prevIte] == pop[i])
            current = prevIte;
        if(nextIte != -1 && push[nextIte] == pop[i])
            current = nextIte;
        if(current == temp)
            return false;
    }
    return true;
}

int main(){
    int array1[] = {1,2,3,4,5,6};
    int array2[] = {3,4,5,6,2,1};
    
    printf("The order is %s", IsPopOrder(array1, array2, 6, 6) ? "valid" : "invalid");
}

 

书中的思路是:定义一个栈,从而模拟整个序列的压入和弹出。在弹出序列每读到一个值,如果其不在栈顶,就将压入序列中这个值,以及之前的值都一起压入栈中。弹出这个值。

返回false的条件是,所读入的弹出序列中的值既不在栈顶,又不在压入序列中。

书中代码:

#include "stdafx.h"
#include <stack>

bool IsPopOrder(const int* pPush, const int* pPop, int nLength)
{
    bool bPossible = false;

    if(pPush != NULL && pPop != NULL && nLength > 0)
    {
        const int* pNextPush = pPush;
        const int* pNextPop = pPop;

        std::stack<int> stackData;

        while(pNextPop - pPop < nLength)
        {
            // 当辅助栈的栈顶元素不是要弹出的元素
            // 先压入一些数字入栈
            while(stackData.empty() || stackData.top() != *pNextPop)
            {
                // 如果所有数字都压入辅助栈了,退出循环
                if(pNextPush - pPush == nLength)
                    break;

                stackData.push(*pNextPush);

                pNextPush ++;
            }

            if(stackData.top() != *pNextPop)
                break;

            stackData.pop();
            pNextPop ++;
        }

        if(stackData.empty() && pNextPop - pPop == nLength)
            bPossible = true;
    }

    return bPossible;
}

 

posted on 2014-01-20 08:49  Felix Fang  阅读(190)  评论(0)    收藏  举报

导航