《剑指offer》第三十一题:栈的压入、弹出序列
// 面试题31:栈的压入、弹出序列 // 题目:输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是 // 否为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1、2、3、4、 // 5是某栈的压栈序列,序列4、5、3、2、1是该压栈序列对应的一个弹出序列,但 // 4、3、5、1、2就不可能是该压栈序列的弹出序列。 #include <cstdio> #include <stack> bool IsPopOrder(const int* pPush, const int* pPop, int nLength) { bool isPossible = false; //鲁棒性检测 if (pPush != nullptr && pPop != nullptr && nLength > 0) { const int* pNextPush = pPush; //const int* 指地址指向的数据是const 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) isPossible = true; } return isPossible; }
// ====================测试代码==================== void Test(const char* testName, const int* pPush, const int* pPop, int nLength, bool expected) { if (testName != nullptr) printf("%s begins: ", testName); if (IsPopOrder(pPush, pPop, nLength) == expected) printf("Passed.\n"); else printf("failed.\n"); } void Test1() { const int nLength = 5; int push[nLength] = { 1, 2, 3, 4, 5 }; int pop[nLength] = { 4, 5, 3, 2, 1 }; Test("Test1", push, pop, nLength, true); } void Test2() { const int nLength = 5; int push[nLength] = { 1, 2, 3, 4, 5 }; int pop[nLength] = { 3, 5, 4, 2, 1 }; Test("Test2", push, pop, nLength, true); } void Test3() { const int nLength = 5; int push[nLength] = { 1, 2, 3, 4, 5 }; int pop[nLength] = { 4, 3, 5, 1, 2 }; Test("Test3", push, pop, nLength, false); } void Test4() { const int nLength = 5; int push[nLength] = { 1, 2, 3, 4, 5 }; int pop[nLength] = { 3, 5, 4, 1, 2 }; Test("Test4", push, pop, nLength, false); } // push和pop序列只有一个数字 void Test5() { const int nLength = 1; int push[nLength] = { 1 }; int pop[nLength] = { 2 }; Test("Test5", push, pop, nLength, false); } void Test6() { const int nLength = 1; int push[nLength] = { 1 }; int pop[nLength] = { 1 }; Test("Test6", push, pop, nLength, true); } void Test7() { Test("Test7", nullptr, nullptr, 0, false); } int main(int argc, char* argv[]) { Test1(); Test2(); Test3(); Test4(); Test5(); Test6(); Test7(); return 0; }
分析:举例子分析复杂问题来捋顺思路。
注意:pNextPush - pPush == nLength 中,同一空间内两个地址之差为 p - q = (p地址 - q地址) / sizeof(int)。代码中pPush溢出后相减为5。
class Solution { public: bool IsPopOrder(vector<int> pushV,vector<int> popV) { bool isPossible = false; int nLength = pushV.size(); int popLength = popV.size(); if (pushV.size() > 0 && popV.size() > 0 && nLength == popLength && nLength > 0) { int pushNext = 0; int popNext = 0; std::stack<int> stackData; while (popNext < nLength) //弹出序列匹配完成跳出 { while (stackData.empty() || stackData.top() != popV[popNext]) //压入元素入栈直到栈顶为弹出元素 { if (pushNext == nLength) //压入序列为空 break; stackData.push(pushV[pushNext]); ++pushNext; } if (stackData.top() != popV[popNext]) //栈顶元素不为下一个弹出序列 break; stackData.pop(); popNext++; } if (stackData.empty() && popNext == nLength) isPossible = true; } return isPossible; } };