代码随想录算法训练营第10天|栈与队列|232.用栈实现队列225.用队列实现栈

代码随想录算法训练营第10天|栈与队列|232.用栈实现队列225.用队列实现栈

一、232.用栈实现队列

文档链接:代码随想录

题目链接:232.用栈实现队列

视频讲解:视频讲解

题目描述:

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

实现 MyQueue 类:

  • void push(int x) 将元素 x 推到队列的末尾
  • int pop() 从队列的开头移除并返回元素
  • int peek() 返回队列开头的元素
  • boolean empty() 如果队列为空,返回 true ;否则,返回 false

说明:

  • 只能 使用标准的栈操作 —— 也就是只有 push to top, peek/pop from top, size, 和 is empty 操作是合法的。
  • 你所使用的语言也许不支持栈。你可以使用 list 或者 deque(双端队列)来模拟一个栈,只要是标准的栈操作即可。

示例 1:

输入:
["MyQueue", "push", "push", "peek", "pop", "empty"]
[[], [1], [2], [], [], []]
输出:
[null, null, null, 1, 1, false]

解释:
MyQueue myQueue = new MyQueue();
myQueue.push(1); // queue is: [1]
myQueue.push(2); // queue is: [1, 2] (leftmost is front of the queue)
myQueue.peek(); // return 1
myQueue.pop(); // return 1, queue is [2]
myQueue.empty(); // return false

提示:

  • 1 <= x <= 9
  • 最多调用 100pushpoppeekempty
  • 假设所有操作都是有效的 (例如,一个空的队列不会调用 pop 或者 peek 操作)

进阶:

  • 你能否实现每个操作均摊时间复杂度为 O(1) 的队列?换句话说,执行 n 个操作的总时间复杂度为 O(n) ,即使其中一个操作可能花费较长时间。

代码:

思路:理解栈与队列的原理与区别。

    • 先进后出,后进先出
    • 只允许在固定的一端进行插入和删除操作
    • 压栈(入栈)指的是将元素放入栈顶的操作
    • 出栈则是将栈顶元素取出
  • 队列
    • 先进先出
    • 入队指的是将元素放入队尾
    • 出队指的是将队首元素取出
class MyQueue:
    def __init__(self):
        self.stack_in = []  # 输入栈,用于push操作
        self.stack_out = []  # 输出栈,用于pop和peek操作

    def push(self, x: int) -> None:
        self.stack_in.append(x)  # 将元素x入栈

    def pop(self) -> int:
        if not self.stack_out:  # 如果输出栈为空
            while self.stack_in:  # 将输入栈的元素一次弹出并压入到输出栈里
                self.stack_out.append(self.stack_in.pop())
        return self.stack_out.pop()  # 弹出输出栈的栈顶元素

    def peek(self) -> int:
        if not self.stack_out:  # 如果输出栈为空
            while self.stack_in:  # 将输入栈的元素一次弹出并压入到输出栈里
                self.stack_out.append(self.stack_in.pop())
        return self.stack_out[-1]  # 返回栈顶元素,即为队列的开头元素

    def empty(self) -> bool:
        return not self.stack_in and not self.stack_out
        # 如果输入栈和输出栈都为空,则队列为空,返回 True;否则,返回 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.用队列实现栈

文档链接:代码随想录

题目链接:225.用队列实现栈

视频讲解:视频讲解

题目描述:

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

实现 MyStack 类:

  • void push(int x) 将元素 x 压入栈顶。
  • int pop() 移除并返回栈顶元素。
  • int top() 返回栈顶元素。
  • boolean empty() 如果栈是空的,返回 true ;否则,返回 false

注意:

  • 你只能使用队列的基本操作 —— 也就是 push to backpeek/pop from frontsizeis empty 这些操作。
  • 你所使用的语言也许不支持队列。 你可以使用 list (列表)或者 deque(双端队列)来模拟一个队列 , 只要是标准的队列操作即可。

示例:

输入:
["MyStack", "push", "push", "top", "pop", "empty"]
[[], [1], [2], [], [], []]
输出:
[null, null, null, 2, 2, false]

解释:
MyStack myStack = new MyStack();
myStack.push(1);
myStack.push(2);
myStack.top(); // 返回 2
myStack.pop(); // 返回 2
myStack.empty(); // 返回 False

提示:

  • 1 <= x <= 9
  • 最多调用100pushpoptopempty
  • 每次调用 poptop 都保证栈不为空

**进阶:**你能否仅用一个队列来实现栈。

代码:

思路:使用双端队列(deque)来实现栈的基本操作。双端队列是一个可以从两端插入和删除的序列,因此它可以用来模拟栈的行为。

  • 双队列
from collections import deque
class MyStack:
 
    def __init__(self):  # 初始化方法,当创建MyStack类的实例时会自动调用。  
        self.queue1 = deque()  # 创建一个名为queue1的deque对象,用于模拟栈的底层数据结构。  
        self.queue2 = deque()  # 创建一个名为queue2的deque对象,用于在pop操作时交换两个队列。  
  
    def push(self, x: int) -> None:  # push方法,用于向栈顶添加一个整数x。  
        self.queue1.append(x)  # 将x添加到queue1的右侧。  
  
    def pop(self) -> int:  # pop方法,用于从栈顶删除一个整数并返回它。  
        if not self.queue2:  # 如果输出栈为空
            while len(self.queue1) > 1:  # 遍历queue1的左侧元素(除了最后一个)。  
                self.queue2.append(self.queue1.popleft())  # 将每个元素从queue1左侧移除并添加到queue2的右侧。  

            # 交换两个队列的对象引用,使得原本的queue1现在指向被pop操作后的queue2,而原本的queue2现在指向原始的空队列。 
            self.queue1, self.queue2 = self.queue2, self.queue1
        return self.queue2.popleft()  # 返回被pop操作后的队列的第一个元素(即原来的栈顶元素)。
          
    def top(self) -> int:  # top方法,用于返回栈顶的整数,但不删除它。
        return self.queue1[-1]  # 返回queue1中的最后一个元素,即原来的栈顶元素。
  
    def empty(self) -> bool:  # empty方法,用于检查栈是否为空。
        return not self.queue1  # 如果queue1为空,则返回True,否则返回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()
  • 单队列
from collections import deque
class MyStack:
    # 初始化方法,当创建MyStack类的实例时会自动调用
    def __init__(self):
        # 创建一个名为queue的deque对象,用于模拟栈的底层数据结构
        self.queue = deque()

    # push方法,用于向栈顶添加一个整数x
    def push(self, x: int) -> None:
        # 将x添加到queue的右侧
        self.queue.append(x)

    # pop方法,用于从栈顶删除一个整数并返回它
    def pop(self) -> int:
        # 如果栈为空(即queue为空),则返回None
        if self.empty():
            return None
        # 循环地将元素从queue的左侧移到右侧,直到只剩下一个元素。这样做的目的是为了保持deque的有序性,以便能够正确地返回栈顶元素。
        for i in range(len(self.queue) - 1):
            self.queue.append(self.queue.popleft())
        # 返回从queue左侧弹出的元素(即原来的栈顶元素)
        return self.queue.popleft()

    # top方法,用于返回栈顶的整数,但不删除它
    def top(self) -> int:
        # 返回queue的最后一个元素,即栈顶元素。这里不需要进行任何检查,因为如果栈为空,pop和top方法会返回None。
        return self.queue[-1]

    # empty方法,用于检查栈是否为空
    def empty(self) -> bool:
        # 如果queue为空,则返回True,否则返回False。
        return not self.queue

# 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()

你可能感兴趣的:(算法,算法,python,数据结构)