题目
输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1、2、3、4、5是某栈的压栈序列,序列4、5、3、2、1是该压栈序列对应的一个弹出序列,但4、3、5、1、2就不可能是该压栈序列的弹出序列。
解题思路
建立一个辅助栈,把输入的第一个序列中的数据依次压入该辅助栈,并按照第二个序列的顺序依次从该栈中弹出数字。
如,压栈序列:1、2、3、4、5;弹出序列4、5、3、2、1;辅助栈为空;先判断辅助栈与弹出序列的栈顶元素是否相同,辅助栈为空,而pop序列的第一个元素是4,则从push序列中,取第一个入栈元素1,压入辅助栈。此时辅助栈中元素为:1; 继续判断与pop序列第一个元素是否相等,不等,又将push的2压入辅助栈中,直到辅助栈中压入4为止。此时,辅助栈中元素与pop栈顶元素4相等,辅助栈将4弹出,剩下:3、2、1;pop序列则移动到下一个元素5,继续从辅助栈中查找,没有,则继续将push栈中最后的一个元素5压入辅助栈中。push序列已经遍历完成。辅助栈中有:5、3、2、1; 其中5与pop栈顶元素相同,则辅助栈将5弹出,pop序列(用数组表示)又往后移动一位。继续比较省下的3、2、1等元素,直到在辅助栈中找到所有的元素,如果全部找到,则表示pop序列是push序列一个对应的出栈序列。否则,不是。
代码
#include <iostream>
#include <stack>
using namespace std;
// 判断一个序列是否为栈的一个正确出栈序列
// pPush:栈元素的入栈序列
// pPop:栈元素的出栈序列
// nLength: pPop的长度
bool IsPopOrder(const int* pPush, const int* pPop, int nLength)
{
bool bPossible = false; // 结果
if (pPush != nullptr && pPop != nullptr && nLength > 0)
{
const int* pNextPush = pPush; // pNextPush表示pPush移动的标记位
const int* pNextPop = pPop; // pNextPop表示pPop移动的标记位
// 辅助栈,用入压入pPush中的元素,弹出pPop的元素
std::stack<int> stackData;
// 当出栈序列遍历结束,退出循环
while (pNextPop - pPop < nLength)
{
// 如果stackData栈顶元素与pPop栈顶元素不同,则往stackData中压入pPush中的元素
while (stackData.empty() || stackData.top() != *pNextPop)
{
// 当pPush中的元素全部压入辅助栈(stackData)中,则退出循环
if (pNextPush - pPush == nLength)
break;
// 往辅助栈中压入pPush中的元素,并向后移动pPush
stackData.push(*pNextPush);
++pNextPush;
}
// 如果在不断的压栈的过程中,未能找到入pPop栈顶相匹配的元素,则pPop不是一个正确的出栈序列
if (stackData.top() != *pNextPop)
break;
// 如果辅助栈中的栈顶元素与pPop栈顶元素相同,则stackData弹出元素,pNextPop后移
stackData.pop();
++pNextPop;
}
// 如果辅助栈中所有元素都已弹出,且出栈序列中所有元素都已经出栈,则返回成功
if (stackData.empty() && pNextPop - pPop == nLength)
bPossible = true;
}
return bPossible;
}
int main()
{
int push[] = {1,2,3,4,5,6,7};
int pop_1[] = {4,5,3,6,2,7,1};
int pop_2[] = {7,6,4,5,3,2,1};
cout << "pop_1 is " << IsPopOrder(push, pop_1, 7) << endl;
cout << "pop_2 is " << IsPopOrder(push, pop_2, 7) << endl;
return EXIT_SUCCESS;
}