leetcode算法训练第九天| 栈与队列理论基础,232.用栈实现队列,225. 用队列实现栈

文章讲述了栈与队列的基本概念,重点介绍了如何在Python的collections库中使用deque实现栈和队列,以及如何用栈和队列解决LeetCode上的相关问题,如用栈模拟队列和用队列模拟栈。
摘要由CSDN通过智能技术生成

栈与队列理论基础

        首先先总结一下最基础的内容:栈(stack)遵循后进先出(LIFO),队列(queue)遵循先进先出(FIFO)。

        然后总结一下python的collection库中栈与队列实现的底层容器。在collection中,栈和队列都是由deque(双向链表)所实现的,而且不同于C++,collection中是无法指定实现其功能的底层容器的。只有在了解了栈与队列实现的底层容器与机制后我们才可以更好的去解决算法题目。

232. 用栈实现队列

学习视频:栈的基本操作! | LeetCode:232.用栈实现队列_哔哩哔哩_bilibili

学习文档:代码随想录 (programmercarl.com)

学习时间:15:35-16:23

记录时间:16:24-16:45

状态:已听懂|可单独复写代码(定义class还不熟练)|暂不需复习

1. 看到问题后的初始想法

        第一眼看到这题目就感觉仅仅使用一个栈是无论如何都实现不了队列的,可惜由于思维就局限并没有想到可以使用两个栈解决问题,下意识就认为只可以使用一个栈了,以后得改正。

2. 看完随想录后的迭代想法

        十分巧妙的是,本题可以使用两个栈来解决问题。由于我们使用的语言是python,在不掉collection包的情况下没有stack这个数据结构,所以本题我们使用数组来替代stack。尽管我们使用数组来代替栈,但我们还是只用栈的函数来解决问题,不会使用队列独有的函数来解决问题。我们首先定义一个列表叫stack_in,再定义一列表叫stack_out。stack_in是用来存储push进来的元素的,stack_out是用来记录pop出去的元素的。具体来讲,当队列使用push时,我们把元素append进stack_in中。当我们要pop时,我们先判断stack_out有没有元素,如果stack_out有元素,那我们就pop stack_out中的元素,如果没有元素,我们就把stack_in中的所有元素pop出,并依次装入stack_out中(完成stack中元素的反向排列,这样stack_out的最后一个元素就是我们在队列中要得到的元素。(注意:stack_in的元素进入stack_out后所有元素都反向排列了。

代码如下(要注意python class的定义与使用):

class MyQueue(object):

    def __init__(self):
        self.stack_in = []
        self.stack_out = []


    def push(self, x):
        """
        :type x: int
        :rtype: None
        """
        self.stack_in.append(x)


    def pop(self):
        """
        :rtype: int
        """
        if not self.stack_out:
            while self.stack_in:
                self.stack_out.append(self.stack_in.pop())
        ans = self.stack_out.pop()
        return ans



    def peek(self):
        """
        :rtype: int
        """
        ans = self.pop() # 一定要懂得复用函数
        self.stack_out.append(ans)
        return ans


    def empty(self):
        """
        :rtype: bool
        """
        if not self.stack_in and not self.stack_out:
            return True
        else:
            return False



# Your MyQueue object will be instantiated and called as such:
# obj = MyQueue()
# obj.push(x)
# param_2 = obj.pop()
# param_3 = obj.peek()
# param_4 = obj.empty()

 225. 用队列实现栈

学习视频:队列的基本操作! | LeetCode:225. 用队列实现栈_哔哩哔哩_bilibili

学习文档:代码随想录 (programmercarl.com)

学习时间:16:45-17:29

记录时间:17:29-

状态:已听懂|可单独复写代|暂不需复习

 1. 看到问题后的初始想法

        说实话,第一次看到这题我感觉有点多此一举。因为队列和栈本身就不是底层容器,而使用队列去实现栈给人一种叠积木而不是从底层开始构建的感觉。不过这既然是一道算法题、一道面试题,其更多的是考验我们的思路以及对于栈和队列的掌控能力,本身就不具备多少实用价值。我偷偷扫了眼题解,看到用双队列和单队列都可以,我就先脑内构思了下双队列,发现这个双队列和上一题的双栈还不一样,双栈是通过改变数据输出方向来达到目的,而双队列的话无法改变数据方向,纠结了一会,无果,遂思考单队列。由于单队列就那几个操作,因此我想到了一个很“蠢”但可行的方法,即为了使队列输出最后一个元素,我只要把最后一个元素之前的元素全部按顺序pop出来,再按先后顺序push进去,最后再pop最后一个元素(此时最后一个元素已经在队列第一个了)即可。而只要完成相对来说最复杂的pop操作,其他的操作也就很简单了。top函数只要在pop函数的基础上把pop出来的数字再塞回队列最后一个即可。

        但对于python来说,如果使用数组来充当队列,时间复杂度是很高的。每次数组pop出第一个元素,复杂度就是o(n),然而我们要循环size-1次以达到最后一个元素!因此复杂度就是o(n2),和stack的pop o(1)来说简直没法比。

class MyStack(object):

    def __init__(self):
        self.queue = []
        self.size = 0


    def push(self, x):
        """
        :type x: int
        :rtype: None
        """
        self.queue.append(x)
        self.size += 1


    def pop(self):
        """
        :rtype: int
        """
        for i in range(self.size-1):
            temp = self.queue.pop(0)
            self.queue.append(temp)
        ans = self.queue.pop(0)
        self.size -= 1
        return ans


    def top(self):
        """
        :rtype: int
        """
        ans = self.pop()
        self.queue.append(ans)
        self.size += 1
        return ans


    def empty(self):
        """
        :rtype: bool
        """
        if self.size == 0:
            return True
        else:
            return False



# Your MyStack object will be instantiated and called as such:
# obj = MyStack()
# obj.push(x)
# param_2 = obj.pop()
# param_3 = obj.top()
# param_4 = obj.empty()

2. 看完随想录后的迭代想法

        单队列法居然和我刚开始想的一摸一样!(出息了哈哈哈哈)这里补充一下双队列,这里双队列的使用方法也很“质朴”,和单队列的区别就是pop的时候把最后一个元素之前的所有元素都存在了第二个队列里面,等把最后一个元素返回后再重新移回来。。。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值