栈的压入、弹出序列

本文介绍一种高效算法来判断给定的两个序列是否分别代表了栈的有效压入和弹出序列。通过创建辅助栈并对比序列元素,快速验证序列的有效性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

栈的压入、弹出序列

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

题解:
我的思路:
中心思想是,按照顺序取出popV中的第一个数字num,并且记下一个popV中的数字num_next,判断num和num_next在pushV中的顺序,num_next只能在num的左面第一个,或者右面
功力不行,实现起来很麻烦

我之前想的是:创建一个空stack,之后每一步都有两种可能,但只能选择其一,一是从pushV中取出数字,压入stack;二是从stack中取出数字。然后记录所有的,从stack中取出数字的顺序,最后判断popV是否在这个顺序列表里,更加麻烦,之后看了评论发现了一种更好的思路。

更好的思路:
先创建一个空栈stack,然后判断popV[0]和pushV[0]是否相等,相等的话,就直接将其从两个列表里取出;如果不相等,那么再判断stack[-1]是否和popV[0]是否相等,相等的话,将其从栈和列表中取出;如果还不相等的话,将pushV[0]入栈


这个相当于是一个相亲过程,pushV是钻石男,popV是钻石女,然后创建一个空的stack是剩男。然后开始相亲,规则是,钻石男依次让排在钻石女首位的挑选,如果钻石女首位对其不满意,即两个数字不相等,就将钻石男压入剩男,即:

elif pushV:
    stack.append(pushV.pop(0))

如果钻石女对其满意,即数字相等,则两个人都出列去度蜜月,即:

if pushV and popV[0]==pushV[0]:
	popV.pop(0)
	pushV.pop(0)

然后让下一个钻石女相亲,首先让其看最后一个进入剩男的是否合适,即:

elif stack and stack[-1]==popV[0]:
    stack.pop()
    popV.pop(0)

如果最后都没有合适的,就认为失败。

下面是两种思路的代码

# 我的思路
# -*- coding:utf-8 -*-
class Solution:
    def IsPopOrder(self, pushV, popV):
        # write code here
        while popV:
        	# 依次取出pop的数字
            num = popV.pop(0)
            # 如果这个数字不在pushV中,就直接返回false
            if num not in pushV:
                return False
            # 找到这个数字在pushV中的索引
            index = pushV.index(num)
            # 为了防止超出pushV的索引,判断如果索引是0的话有两种可能
            if index == 0:
            	# 第一种可能是 这是最后一个pop的数字
                if len(pushV) == 1:
                	# 如果相等,则返回True
                    if num == pushV[0]:
                        return True
                # 第二种可能是,这个数字仅仅是在pushV中索引为0,不一定什么时候取出
                if popV[0] in pushV[index + 1 : ]:
                    pushV.pop(index)
                else:
                    return False
            # 这个是同样道理,为了防止超出列表索引
            elif index+1 == len(pushV):
                if popV[0] == pushV[index -1]:
                    pushV.pop(index)
                else:
                    return False
            # 判断,下一个pop的数字,是否在push队列中,排在当前pop的数字的左面一个,或者在其右面即可
            elif popV[0] == pushV[index-1] or (popV[0] in pushV[index+1 : ]):
                    pushV.pop(index)
            else:
                return False
        return True

# 大神版
# -*- coding:utf-8 -*-
class Solution:
 
    def IsPopOrder(self, pushV, popV):
        # stack中存入pushV中取出的数据
        stack=[]
        while popV:
            # 如果第一个元素相等,直接都弹出,根本不用压入stack
            if pushV and popV[0]==pushV[0]:
                popV.pop(0)
                pushV.pop(0)
            #如果stack的最后一个元素与popV中第一个元素相等,将两个元素都弹出
            elif stack and stack[-1]==popV[0]:
                stack.pop()
                popV.pop(0)
            # 如果pushV中有数据,压入stack
            elif pushV:
                stack.append(pushV.pop(0))
            # 上面情况都不满足,直接返回false。
            else:
                return False
        return True
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值