【 剑指Offer 】栈的压入,弹出序列

前言:

关于算法这部分,我本来不想写博客,奈何这道题太经典了,是我曾经一直非常疑惑的问题。如今终于得到解决。

题目:

在这里插入图片描述
曾经我无数次疑惑,应该怎么判定一个序列是否是一个栈的弹出序列,如今终于悟了,核心就在于,当前元素是否是进栈后立即出栈, 如果进栈后立即出栈,那么就可以判断当前出栈元素的下一个元素是否是栈顶元素,如果是,则继续出栈。

核心就是一个消消乐的思想,只要匹配了,就看栈里面是否还能弹出,有时候会弹出一大串元素,如果不匹配,就继续入栈堆下去,等待下一个匹配的元素。

代码:

class Solution {
public:
    bool IsPopOrder(vector<int> pushV,vector<int> popV) {
        stack<int > s;//真正入栈的元素
        for(int i=0,j=0;i<pushV.size();){
            if(pushV[i]==popV[j]){
                i++;j++;
                while(!s.empty()&&popV[j]==s.top()){
                    s.pop();j++;
                }
            }else{
                s.push(pushV[i]);
                i++;
            }
        }
        return s.empty();
    }
};

解析:

普通模拟版:

这个代码的思想就是维护一个真正的栈,以及一个指向入栈序列的指针( i ),一个指向出栈序列的指针( j )。看指向入栈的指针和指向出栈的指针的值,能否匹配的问题。

在普通版这里,就是真的模拟一下栈的入栈出栈序列。

初始状态如图所示:
在这里插入图片描述
此时i指向的元素1入栈,i指向下一个入栈的元素:
在这里插入图片描述
此时注意到栈中元素1与弹出序列匹配了,说明元素1,进栈后立即出栈了,故元素1出栈,j++,j指向下一个匹配的出栈元素。
在这里插入图片描述
此时i指向的元素2入栈,i++,指向下一个入栈元素:
在这里插入图片描述
此时栈顶元素与j指向的元素不匹配,说明元素2并没有入栈后立即出栈。那么就继续入栈,将i指向的元素入栈,i++,指向下一个入栈元素:
在这里插入图片描述
此时栈顶元素与j所指向的元素匹配,说明元素3入栈后马上就出栈了,将栈顶元素弹出。j++指向下一个弹出元素。
在这里插入图片描述
此时栈顶元素还是和j指向的元素相同,所以栈顶元素继续弹出。j++,指向下一个弹出的元素。
在这里插入图片描述
此时栈顶元素无法在和j指向的元素匹配,说明i指向的元素需要继续入栈,i++,指向下一个入栈元素:
在这里插入图片描述
此时栈顶元素,与j指向的元素匹配,说明栈顶元素又该出栈了。j++,指向下一个需要匹配的元素:
在这里插入图片描述
此时栈空了,需要继续入栈元素,但是入栈序列已经空了,说明之前入栈的序列都被匹配完了,都是正确匹配。也就是出栈序列是可以由入栈序列得出的,最后的结果由栈是否为空表示是否成功匹配。

优化版:

这个代码的思想就是维护一个真正的栈,以及一个指向入栈序列的指针( i ),一个指向出栈序列的指针( j )。看指向入栈的指针和指向出栈的指针的值,能否匹配的问题。

初始状态如图所示:
在这里插入图片描述

如图所示,一开始i指向的元素等于j指向的元素,说明元素1刚刚入栈,就出栈了,也就是元素1其实没必要入栈,因为刚进就出,无意义,此时i++,j++,i自增的原因是需要入栈下一个元素,j自增是因为已经匹配了弹出序列,下面需要匹配剩下的弹出序列了。此时状态如下图所示:
在这里插入图片描述
此时,i和j指向的元素不相等,这时就需要将i指向的元素暂存到栈中,之后i自增,寻找下一个和j指向的出栈元素相匹配的元素。
在这里插入图片描述
此时2已经入了栈,i指向了元素3,现在i和j指向的元素又相等了,说明元素3,也是入栈之后立即又出了栈,也就是没必要将元素3入栈,无意义,此时i++,j++,如上所述,i自增是为了下一个入栈元素,j自增是为了匹配下一个弹出元素。
在这里插入图片描述

这里有需要注意的一个地方,现在元素3入了栈,就马上出栈,也就是随之而来的就是当前栈顶元素是否会出栈。所以需要匹配一下,当前情况下,已经存储到栈中的元素2是否会出栈。这里元素2会出栈,所以接下来就是。
在这里插入图片描述
如上图所示,此时i和j又指向了相同的元素,所以i++,j++:
在这里插入图片描述

此时i已经大于了入栈序列,所以程序结束。

判断一个入栈序列是否能够匹配对应的弹出序列的结果,就是最后栈中是否有剩余的元素,这里栈空,说明成功匹配了。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值