栈的压入、弹出序列

输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列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();
    }
};




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值