队列、栈的互相实现及快速获取最大最小值等相关问题汇总

1.两个栈实现一个队列

JZ9:用两个栈实现队列

思路:

不用每次出队完后都把栈B的元素倒腾回栈A。而是依照以下原则:
入队都进栈A,出队都从栈B出,一旦要出队但栈B为空,就将栈A元素依次弹出并入栈B
复杂度分析:由于每个元素都经历了进A出A和进B出B,因此时间复杂度o(n),空间复杂度o(n)
在这里插入图片描述
代码实现:

class Solution:
    def __init__(self):
        self.stack1 = []
        self.stack2 = []
    def push(self, node):
        # write code here
        self.stack1.append(node)
    def pop(self):
        if not self.stack2:
            if not self.stack1:
                raise 
            while self.stack1:
                self.stack2.append(self.stack1.pop())
        return self.stack2.pop()

2.两个队列实现一个栈

思路:

栈是遵循后入先出,而队列是先入先出。可以考虑两个队列,当要出栈时将队列1中的元素逐个出队列并加入队列2中,弹出最后一个队尾元素值返回,那么这个就是栈顶元素。入栈则直接将元素加入到队列中。总的来说,每次执行出栈操作时都要将队列元素倒腾一遍,才能获得队尾元素。【其中一个小细节技巧是,每次倒腾完,交换两个队列变量的引用,保证queue1始终是指向有元素的,这样在入队列时就统一加在queue1中,而不用根据是否有元素去判断加在哪一个queue了】
在这里插入图片描述

3.获取栈的最小/最大值

JZ30 包含min函数的栈

思路:

最直观的思路是维护一个最小值,但如果出栈的元素为最小值,又要重新去找栈中的最小值,比较麻烦。因此可考虑外加一辅助栈保存当前栈高的最小值,与数据栈同步执行入栈和出栈操作。
辅助栈的维护规则为:若进栈的元素比mival栈顶元素小则更新栈顶元素,否则重复mival栈顶元素。
这样做的本质是将每一时刻的最小值都保存了下来,所以即使当前最小值元素出栈了,也能直接得到剩余元素的最小值【根据栈的特性,出栈时的元素状态一定在当初进栈时存在过,因此在进栈时就已经得到过当前状态的最小值。而队列不满足该特性,所以该方法对队列不适用】。

在这里插入图片描述
在这里插入图片描述
代码实现:

# -*- coding:utf-8 -*-
class Solution:
    def __init__(self):
        self.stack, self.stackMin = [], []
    def push(self, node):
        # write code here
        self.stack.append(node)
        if self.stackMin:
            self.stackMin.append(min(self.stackMin[-1], node))
        else:
            self.stackMin.append(node)
        return node
    def pop(self):
        # write code here
        self.stackMin.pop()
        return self.stack.pop()
    def top(self):
        # write code here
        return self.stack[-1]
    def min(self):
        # write code here
        return self.stackMin[-1]

4.获取队列的最小/最大值

相关题目:JZ59 滑动窗口的最大值

思路:

由于队列先进先出的特点,当前状态并没有相应的历史状态。因此上述栈的方法并不适用于队列。前面提到过队列可以用两个栈实现。那么我们可以考虑对两个栈分别设置最值辅助栈,来实现这一功能。
栈A和栈B中的所有元素集合为队列中的元素。而最值辅助栈A和栈B的栈顶元素分别代表两个栈中的最值,只需对这两个值进行比较即可。
可以看到在4、2、1分别出队时,依旧能从栈maxvalB中快速获得最值。这样做的本质是把队列看成了一个反向栈,在将队列反向入B栈时,把所有数据正向出队列的情形都遍历了一遍并保存。
在这里插入图片描述
注:也可以用JZ59的方法。新开一个队列,后入队的大元素可以把队列中的小元素挤出去。这是因为后入队的一定比先入队的元素后出去,如果还比前面元素大的话,那就永远轮不上前面元素了,所以可以直接排除,这样队列的第一个值一定是最大值。但要注意这个最大值随时可能会出队,所以每次出队后都要判断一下该元素是否还在队列中,不在则要弹出。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值