美文网首页剑指Offer-Python-牛客网
面试题31:栈的压入、弹出序列

面试题31:栈的压入、弹出序列

作者: 凌霄文强 | 来源:发表于2019-01-09 16:03 被阅读0次

    题目描述

    输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。(注意:这两个序列的长度是相等的)

    知识点


    Qiang的思路

    对于一个栈,当压入序列确定时,当给出第一个弹出元素,就会将压入序列分成两段,对于前半段的元素必须先弹出后面的,因为此时前半段全被压入栈中,但是后半段元素可以任意弹出,因为后半段的压入情况不确定。然后对于第二个弹出元素时,我们需要从上一时刻的位置往后遍历,如果遇到相同的那就是这个元素弹出了 ,如果没有那么需要往前遍历。在往前遍历时,如果遇到的第一个未弹出元素和当前弹出元素相等,那么就是这个元素需要弹出,如果不相等那么这个弹出序列并不是压入序列的弹出序列。

    # -*- coding:utf-8 -*-
    class Solution:
        def IsPopOrder(self, pushV, popV):
            # write code here
            if len(popV)==0:
                return True
            pos=-1
            for j in range(len(popV)):
                flag=False
                for i in range(pos+1, len(popV)):
                    if pushV[i]==popV[j]:
                        pushV[i]=None
                        pos=i
                        flag=True
                        break
                if flag==True:
                    continue
                for i in range(pos-1,-1,-1):
                    if pushV[i]==popV[j]:
                        pushV[i]=None
                        pos=i
                        flag=True
                        break
                    if pushV[i]!=None:
                        return False
                if flag==False:
                    return False
            return True
    

    首先需要从上一时刻找到弹出元素的位置出发,往后找,如果找到了弹出元素,则记录该位置,并开始下一轮寻找。如果没有找到,那么需要往前找,但是往前找的时候不用考虑之前弹出的元素,只需要关注第一个未被弹出的元素,如果他和当前弹出的元素相等则继续下一轮寻找,如果不相等则说明不是弹出序列。

    同时,需要注意,可能当前弹出元素都不在压入序列中,所以如果查找了一遍并没有发现弹出元素,那么我们可以提前终止遍历,弹出序列一定不是压入序列的弹出结果。


    Book中的思路

    书中引入了辅助栈的概念,增加是空间复杂度,但是不需要往前遍历,只需要看栈顶元素即可,但是往后遍历还是需要的,所以在一定的程度上降低了时间复杂度。

    # -*- coding:utf-8 -*-
    class Solution:
        def IsPopOrder(self, pushV, popV):
            # write code here
            s=[]
            while popV!=[]:
                c=popV.pop(0)
                if s!=[] and s[-1]==c:
                    s.pop(-1)
                    continue
                flag=False
                while pushV!=[]:
                    _c=pushV.pop(0)
                    if c==_c:
                        flag=True
                        break
                    s.append(_c)
                if flag==False:
                    return False
            return True
    

    每次需要先查看辅助栈的栈顶元素,如果栈顶元素等于当前的弹出元素,那么就找到了弹出元素,如果并不相等,则需要将其他的压入元素压入到栈中,同时比较是不是和当前弹出元素相等,如果遇到一个相等的元素那么便可以结束压入过程,该元素就是弹出元素,如果将所有的元素都压入了栈中还是没有找到,这说明弹出序列并不是压入序列的弹出序列。


    作者原创,如需转载及其他问题请邮箱联系:lwqiang_chn@163.com
    个人网站:https://www.myqiang.top

    相关文章

      网友评论

        本文标题:面试题31:栈的压入、弹出序列

        本文链接:https://www.haomeiwen.com/subject/zikgrqtx.html