题目:输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如,序列{1,2,3,4,5}是某栈的压栈序列,序列{4,5,3,2,1}是该压栈序列对应的一个弹出序列,但{4,3,5,1,2}就不可能是该压栈序列的弹出序列。
思路:
这道题我开始都没看懂是什么意思,序列{1,2,3,4,5}压栈之后,出栈不就是{5,4,3,2,1}?原来题目是说,压栈的时候是这个顺序,但是可以在压栈的过程中穿插出栈操作,比如先压入1,2,3,4再出栈4,再压栈5,再出栈5、3、2、1,这样就得到了出栈序列{4,5,3,2,1}。明白了这个过程之后,建立一个辅助栈,输入的序列为两个数组结构的数据,分别表示压栈顺序和出栈的顺序,把输入的第一个序列中的数字依次压入该辅助栈,并且按照第二个序列的顺序依次从该栈中弹出序列。首先在空的辅助栈里面压入序列一的第一个数字1,发现1和序列二的第一个数字4不相等,那么就不断的将序列一剩下的数压入辅助队列,直到压入的数也为4,如果序列一全部数字都压入辅助序列后也没有找到相等的数字(这里为4),那么这个序列肯定不是一个有效的弹出序列。这里目前压入辅助栈的数字为1、2、3、4,这个时候我们将辅助序列和第二个序列的栈首数字4同时出栈,第二个序列的首元素变成了5,和辅助栈的首元素3不相等,那么就继续从序列一中压入元素,直到压入5为止,这个时候辅助栈的序列为1 2 3 5,栈首元素和第二栈的首元素相等,那么辅助栈和第二个序列同时将5出栈,此时,辅助栈变为了1 2 3 ,第二个栈也变成了1 2 3,这个时候同时再出栈3 ,又发现栈的首元素都为2,继续出栈2,接着出栈1,这个时候辅助栈为空,序列二也为空,说明第二个序列是第一个序列的辅助序列。
代码:
bool IsPopOrder(const int* pPush, const int* pPop, int nLength)
{
bool bPossible = false;
if (pPush != nullptr&&pPop != nullptr&&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;
}
还是要注意输入的数组指针为空,或者数组的长度小于等于0的情况的处理。
复习:
这里辅助栈的应用很巧妙,用法要记住。
二刷代码:
bool IsPopOrder(const int* pPush, const int* pPop, int nLength)
{
if (pPop == nullptr || pPop == nullptr||nLength<=0)
return false;
bool bPossible = false;
const int* pNextPush = pPush;
const int* pNextPop = pPop;
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 - pPush == nLength)
bPossible = true;
return bPossible;
}