栈 ~ 思维题

题目:输入两个整数数列,第一个序列表示栈的压入顺序,请判断第二个序列是否是该栈的其中一个弹出顺序。假设压入栈的所有数字均不相等。例如,序列{1,2,3,4,5}是某栈的压栈序列,序列{4,5,3,2,1}是该压栈序列对应的一个弹出序列,但是{4,3,5,1,2}就不可能是该压栈序列对应的一个弹出序列。

思路

解决这个问题很直观的想法就是建立一个辅助栈,把输入的第一个序列中的数字依次压入辅助栈,并按着第二个序列的顺序依次从该栈中弹出数字。

以弹出{序列4,5,3,2,1}为例分析压入栈和弹出的过程。第一个希望被弹出的数字是4.,因此4需要先压入辅助栈,压入栈的顺序由压栈序确定,也就是把4压入栈之前,数字1,2,3都需要压入栈,此时栈中包含数字4.分别是1,2,3,4.其中4位于栈顶,把4弹出栈后,剩下的 数字3位于栈顶,接下来希望被弹出的5,由于它不是栈顶元素,因此我们接着在第一个序列中把4以后的数字压入辅助栈,直到压入数字5,这个时候5位于栈顶,就可以被弹出来了。接下来希望被弹出的是3,2,1.由于每次操作前他们都位于栈顶,因此直接弹出即可。

接下来再分析弹出序列{4,3,5,1,2}。第一个希望被弹出的是4和前面的情况一样。把4弹出之后,3位于栈顶,可以直接弹出,接下来希望被弹出的是5,由于它不是栈顶元素,因此我们接着在第一个序列中把4以后的数字压入辅助栈,直到压入数字5,这个时候5位于栈顶,就可以被弹出来了。此时栈中有两个数字1 ,2,其中2位于栈顶,由于接下来希望被弹出的 数字是1,我们需要从压栈序列中尚未压栈的数字中去搜素这个数字。但是此时所有压栈序列中的数字都已经压栈了,所以该弹出序列不是{1,2,3,4,5}对应的弹出序列。

总结
综上所诉,我们可以找到一个判断一个序列是不是栈的弹出序列的规律:如果下一个弹出数字刚好是栈顶数字,那么直接弹出,如果不是,则把尚未压栈的数字压入辅助栈,直到把下一个弹出的数字压入栈顶为止,如果所有数字都压入后仍然没有找到下一个弹出数字,那么该序列不可能是一个弹出序列。

形成了思路之后,下面附上代码~

bool IsPopOrder(const int* pPush, const int* pPop, int nLength) 
{
    bool bOrderFlag = false;
    if (NULL != pPush && NULL != pPop && nLength > 0) {
        const int* pNextPush = pPush;
        const int* pNextPop = pPop;
        std::stack<int> pStack;
        while (pNextPop - pPop < nLength) {//直到弹出序列为空
            while (pStack.empty() || pStack.top() != *pNextPush) {//直到压入栈的数字等于需要弹出的数字
                if (pNextPush - pPush == nLength) {//全部压栈
                    break;
                }
                pStack.push(*pNextPush);
                pNextPush++;
            }
            if (pStack.top() != *pNextPush) {// 匹配失败
                break;
            }
            pStack.pop();
            pNextPop++;
        }
        if (pStack.empty() && pNextPop - pPop == nLength) {//全部匹配成功
             bOrderFlag = true;
        } 
    }
    return bOrderFlag;
}

以上,欢迎留言交流~

猜你喜欢

转载自blog.csdn.net/breakpoints_/article/details/80465728
今日推荐