题目描述
输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。
假设压入栈的所有数字均不相等。
例如序列1,2,3,4,5是某栈的压入顺序,
序列4,5,3,2,1是该压栈序列对应的一个弹出序列,
但4,3,5,1,2就不可能是该压栈序列的弹出序列。
思路:
开辟一个辅助栈,模拟入栈出战过程(假设pa为入栈序列,pb为出战序列)
pa中的元素依次压入辅助栈
新压入的元素与弹出序列的栈底相同,辅助栈弹出,同时pb向上移动
不相同了pa中的元素继续入辅助
如果下一个弹出的数字刚好是栈顶数字,则直接弹出。
若下一个弹出的数字不在栈顶,则把压栈序列中还没有入栈的数字压入辅助栈,直到把下一个需要弹出的数字压入栈顶为止。
若所有的数字都压入栈了仍没有找到下一个弹出的数字,则表明该序列不可能滴一个弹出序列。
#include <iostream>
#include <stack>
#include <vector>
using namespace std;
// 调试开关
#define __tmain main
#ifdef __tmain
#define debug cout
#else
#define debug 0 && cout
#endif // __tmain
class Solution
{
public:
bool IsPopOrder(vector<int> pushV,vector<int> popV)
{
if(pushV.size( ) == 0 || popV.size( ) == 0)
{
return false;
}
stack<int> s;
int push, pop;
s.push(pushV[0]);
debug <<"push" <<pushV[0] <<endl;
for(push = 0, pop = 0;
push < pushV.size() && pop < popV.size( );)
{
if(s.empty( ) != true && s.top( ) == popV[pop]) // 当前栈顶元素正好是出栈序列中的元素
{
debug <<"pop"<<popV[pop] <<endl;
// 模拟出栈的过程
s.pop( );
pop++;
}
else
{
// 模拟入栈的过程
s.push(pushV[++push]);
debug <<"push" <<pushV[push] <<endl;
}
}
if(s.empty( ) == true)
{
return true;
}
else
{
return false;
}
}
};
int __tmain( )
{
int nPush[5] = {1,2,3,4,5};
int nPop1[5] = {4,5,3,2,1};
int nPop2[5] = {4,3,5,1,2};
int nPop3[5] = {5,4,3,2,1};
int nPop4[5] = {4,5,2,3,1};
Solution solu;
cout <<solu.IsPopOrder(vector<int>(nPush, nPush + 5), vector<int>(nPop1, nPop1 + 5)) << endl;
cout <<solu.IsPopOrder(vector<int>(nPush, nPush + 5), vector<int>(nPop2, nPop2 + 5)) << endl;
cout <<solu.IsPopOrder(vector<int>(nPush, nPush + 5), vector<int>(nPop3, nPop3 + 5)) << endl;
cout <<solu.IsPopOrder(vector<int>(nPush, nPush + 5), vector<int>(nPop4, nPop4 + 5)) << endl;
return 0;
}
我们这里用了一个辅助栈来模拟出栈入栈的过程,思路很简单很清晰,但是又没有可以优化的地方么
其实由于当前栈的动作是肯定超不出pushV序列的,因此我们可以直接用PushV入栈序列作为我们的模拟栈,而用top去维护入栈出栈的操作
这种方法时间复杂度$O(n)$,空间复杂度$O(1)$,但是要修改输入参数PushV的值
class Solution
{
public:
bool IsPopOrder(vector<int> pushV,vector<int> popV)
{
if(pushV.size( ) == 0 || popV.size( ) == 0)
{
return false;
}
int top = -1, push = 0, pop = 0;
++top;
debug <<"push" <<pushV[top] <<endl;
while(push < pushV.size() && pop < popV.size( ))
{
if(top != -1 && pushV[top] == popV[pop]) // 当前栈顶元素正好是出栈序列中的元素
{
debug <<"pop"<<popV[pop] <<endl;
// 模拟出栈的过程
top--;
pop++;
}
else
{
// 模拟入栈的过程
pushV[++top] = pushV[++push];
debug <<"push" <<pushV[push] <<endl;
}
}
debug <<top <<push <<pop <<endl;
return (top == -1);
}
};
或者直接使用
class Solution
{
public:
bool IsPopOrder(vector<int> pushV,vector<int> popV)
{
if(pushV.empty( ) || popV.empty( ) || pushV.size( )!= popV.size( ))
{
return false;
}
for(int i = 0;i < pushV.size();)
{
if(pushV[i] == popV[0])
{
pushV.erase(pushV.begin( ) + i);
popV.erase(popV.begin( ));
i--; // 模拟出栈
}
else
{
i++; // 模拟入栈
}
}
return pushV.empty( );
}
};
这个是看到的别人的做法
不一样的思路:
我先取出pop序列的第一个(比如pop【3,2,4,5,1】),在push序列中找到这个位置,push【1,2,3,4,5】,
此时我们找到了3的位置.那么下一个pop的数字(此时的数字是2)必然是,push中3的前一个数字,或者后面的数字。否则返回False 如此循环直到最后,判断长度相等,就是弹出序列。否则返回False.
# -*- coding:utf-8-*-
classSolution:
def IsPopOrder(self, pushV, popV):
# write code here
iflen(pushV) != len(popV):
returnFalse
elif len(pushV) ==0:
returnFalse
x = popV[0]
ifx not in pushV:
returnFalse
fori in range(len(popV)):
position = pushV.index(popV[i])
iflen(pushV) ==1:
ifpushV[0] == popV[i]:
returnTrue
try:
ifpopV[i+1] == pushV[position-1]:
pushV.remove(pushV[position])
elif popV[i+1] in pushV[position:]:
pushV.remove(pushV[position])
else:
returnFalse
except IndexError:
returnFalse
else:
returnTrue