力扣60天刷题挑战 | day11 栈与队列 1/2

104 阅读3分钟

225.用队列实现栈

请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(push、top、pop 和 empty)。

void push(int x) 将元素 x 压入栈顶。

int pop() 移除并返回栈顶元素。

int top() 返回栈顶元素。

boolean empty() 如果栈是空的,返回 true ;否则,返回 false 。

解题思路:

  1. 用两个队列实现栈,需要了解队列特性(先进先出)以及栈特性(先进后出)
  2. 在python中如何实现队列?用collections.deque()功能,并且题目限制了队列的操作
  • push to back 对应deque.append()
  • peek/pop from front对应deque.popleft()
  • size 对应len()
  • is empty,直接判断deque是否为空即可

python官方文档collections.deque()用法

  1. 用deque1作为存储队列,deque2作为辅助队列

详细代码:

class MyStack:

    def __init__(self): # 1.import collections(力扣已经帮忙引入了),初始化队列
        self.deque1 = collections.deque() #存储队列
        self.deque2 = collections.deque() #辅助队列

    def push(self, x: int) -> None:
        self.deque2.append(x) # 2.辅助队列先加个x 
        while self.deque1: # 当存储队列存在元素时,将队列最左端的元素弹出,在放到辅助队列中
            self.deque2.append(self.deque1.popleft())
        self.deque1, self.deque2 = self.deque2, self.deque1 #存储队列与辅助队列对调,记得跳出while

    def pop(self) -> int:
        return self.deque1.popleft() #符合队列peek from front

    def top(self) -> int:
        return self.deque1[0]

    def empty(self) -> bool:
        return not self.deque1 # 注意题目要求,队列非空为true,但是题目要求如果为空是true

做题记录

  1. 花费40分钟:看官方题解且理解15分钟,代码实现5分钟,写题解20分钟
  2. 代码错误:
  • deque.popleft()括号中不带参数;
  • push功能中注意while包含的范围;
  1. 情绪波动:总感觉自己学不会,而且这是刷第二次了吧,全都忘记了,不过先坚持两个月下来再说

232.用栈实现队列

请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(push、pop、peek、empty):

void push(int x) 将元素 x 推到队列的末尾

int pop() 从队列的开头移除并返回元素

int peek() 返回队列开头的元素

boolean empty() 如果队列为空,返回 true ;否则,返回 false

解题思路:

  1. 一开始效仿225题思路,想用一个存储deque以及辅助deque,不过发现不通过(现在还没有发现哪里错了),后来考虑用stack_in和stack_out来完成,也就是进栈和出栈合二为一一起看

代码实现:

第一次解题思路(没有通过):还没有找出错误点……

class MyQueue:

    def __init__(self):
        self.stack1 = collections.deque() # 双端队列表示栈
        self.stack2 = collections.deque()

    def push(self, x: int) -> None:
        self.stack1.append(x)

    def pop(self) -> int:
        while self.stack1:
            self.stack2.append(self.stack1.pop())
        self.stack1, self.stack2 = self.stack2, self.stack1
        return self.stack1.pop()

    def peek(self) -> int:
        return self.stack1[0]

    def empty(self) -> bool:
        return not self.stack1

第二个解题思路:

class MyQueue:

    def __init__(self):
        self.stackin = list() # 用列表表示栈
        self.stackout = list()

    def push(self, x: int) -> None:
        self.stackin.append(x) #输入栈的append跟队列入队顺序是一样的

    def pop(self) -> int:
        if not self.stackout:
            while self.stackin:
                self.stackout.append(self.stackin.pop())
        return self.stackout.pop()

    def peek(self) -> int:
        if not self.stackout:
            while self.stackin:
                self.stackout.append(self.stackin.pop())
        return self.stackout[-1] #这里一开始有个错误!

    def empty(self) -> bool:
        return self.stackin == [] and self.stackout == []

做题记录:

  1. 全程50分钟:做题15分,讨论15分,记录20分
  2. 两道题的代码都可以很快敲出来,问题是什么情况下需要借用辅助列表从而完成一个完整的存储列表(用一完成一),以及什么时候将两个栈看成一个整体(二当成一)。这个思路还没有理清楚,不清楚应用场景
  3. 一个容易犯的错误!!
  • 解答peek(self)的是欧如果直接用return self.pop() 的做法,会改变empty(self)算法改变了。可以迂回地处理如下:
    def peek(self) -> int:
        ans = self.pop() # 1获得队头的元素
        self.stackout.append(ans) # 第一步弹出了,把他恢复
        return ans 
  1. 老实说刷完前一道题这一道题已经比较容易理解了,又觉得可以再坚持刷一刷