输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列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是否是该压栈序列对应的一个弹出序列
第一个出栈元素为4,说明栈中还有元素1,2,3。
这个时候如果继续出栈,出栈元素应该为3。
但如果执行进栈,栈中元素变为1,2,3,5。然后再出栈的话出栈元素就是5。再执行三次出栈操作就是题中这种情况,所以4,5,3,2,1是该压栈序列对应的一个弹出序列。
同样,我们来看为什么4,3,5,1,2就不可能是该压栈序列的弹出序列呢
第一个出栈元素为4,说明栈中还有元素1,2,3。继续出栈,出栈元素为3。栈中剩余元素为1,2。然后5进栈,再出栈,栈中元素还是1,2。这时继续出栈的话只可能是元素2出栈,不可能是1.所以4,3,5,1,2不可能是该压栈序列的弹出序列。
总结:
出栈元素只可能是与上一个出栈元素紧邻的仍在栈中的元素或者是后来又进栈的新元素。
该思路的代码如下:
class Solution {
public:
bool IsPopOrder(vector<int> pushV,vector<int> popV) {
int *flag = new int[pushV.size()];//标记是否还在栈中
for(int i= 0; i<pushV.size(); i++) flag[i] = 0;
vector<int>::iterator iter;
if(pushV.size()==1)//考虑1个元素情况
{
if(popV.size()>1 || pushV[0]!=popV[0]) return false;
}
for(int i= 0; i<popV.size()-1; i++)
{
int value = popV[i];
iter = find(pushV.begin(),pushV.end(),value); //找到出栈的元素在入栈序列中的位置
if(iter == pushV.end()) return false;
flag[iter-pushV.begin()] = 1;//出栈的元素标记为1
while(iter-pushV.begin()>=0&&flag[iter-pushV.begin()] == 1) iter--; //找到与该元素紧邻的仍在栈中的元素
if(popV[i+1] == *iter || find(pushV.begin(),pushV.end(),popV[i+1])> find(pushV.begin(),pushV.end(),value))
continue;//判断下一个出栈元素是否满足之前提到的两种情况
else
return false;
}
return true;
}
};
另外附上一个别人的思路更简单的程序(借用一个辅助栈):
class Solution {
public:
bool IsPopOrder(vector<int> pushV,vector<int> popV) {
if(pushV.size() == 0) return false;
vector<int> stack;
for(int i = 0,j = 0 ;i < pushV.size();){
stack.push_back(pushV[i++]);
while(j < popV.size() && stack.back() == popV[j]){
stack.pop_back();
j++;
}
}
return stack.empty();
}
};