题目:输入两个整数数列,第一个序列表示栈的压入顺序,请判断第二个序列是否是该栈的其中一个弹出顺序。假设压入栈的所有数字均不相等。例如,序列{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;
}
以上,欢迎留言交流~