【剑指 Offer】9, 用两个栈实现队列。 难度等级:简单。解题思路值得学习

1. 题目

用两个栈实现一个队列。队列的声明如下,请实现它的两个函数 appendTail 和 deleteHead ,分别完成在队列尾部插入整数和在队列头部删除整数的功能。(若队列中没有元素,deleteHead 操作返回 -1 )

示例 1:

输入:
["CQueue","appendTail","deleteHead","deleteHead","deleteHead"]
[[],[3],[],[],[]]
输出:[null,null,3,-1,-1]

示例 2:

输入:
["CQueue","deleteHead","appendTail","appendTail","deleteHead","deleteHead"]
[[],[],[5],[2],[],[]]
输出:[null,-1,null,null,5,2]

2. 我的解法:慢

思路:使用一个逆向的辅助栈,每次删除队列头部元素时就使 stack 依次出栈,删除栈底元素后再入栈。

每次删除头部元素都需要执行完整的出栈和入栈操作,其中存在重复操作,导致时间复杂度较高。

code:

class CQueue:
    def __init__(self):
        self.stack=[]
        self.inv_stack=[]   # stack的逆序

    def appendTail(self, value: int) -> None:
        self.stack.append(value)

    def deleteHead(self) -> int:
        if not self.stack:
            return -1
        # stack 逐元素出栈
        while self.stack:
            self.inv_stack.append(self.stack.pop())

        # 在stack 逐元素入栈之前保留队列头部元素
        head=self.inv_stack.pop()

        # stack 逐元素入栈
        while self.inv_stack:
            self.stack.append(self.inv_stack.pop())
        return head
       

# Your CQueue object will be instantiated and called as such:
# obj = CQueue()
# obj.appendTail(value)
# param_2 = obj.deleteHead()

执行结果:

执行用时:1084 ms, 在所有 Python3 提交中击败了 12.81% 的用户
内存消耗:20.2 MB, 在所有 Python3 提交中击败了 17.19% 的用户

3. 进阶解法:快

code:

class CQueue:
    def __init__(self):
        self.stack = []
        self.inv_stack = []

    def appendTail(self, value: int) -> None:
        self.stack.append(value)

    def deleteHead(self) -> int:
        # 每次删除队列头部元素就从 inv_stack 中删除尾部元素,直到 inv_stack 为空
        if self.inv_stack: 
            return self.inv_stack.pop()
        if not self.stack: 
            return -1
        
        # inv_stack 为空时,将 stack 逆序输入到 inv_stack 中
        while self.stack:
            self.inv_stack.append(self.stack.pop())
        return self.inv_stack.pop()

执行结果:

执行用时:312 ms, 在所有 Python3 提交中击败了 70.07% 的用户
内存消耗:20.1 MB, 在所有 Python3 提交中击败了 22.39% 的用户

该解法相比于我的解法,它只执行 stack 的出栈操作,而不执行 stack 的入栈操作。而是通过先返回 self.inv_stack.pop() 的方法确保每次都能返回 队列的头部元素。

该解法能够高效执行的前提是题目中不要求可以随时打印队列全部元素的功能;而在 self.inv_stack 不为空时 self.stack 是空栈,此时是无法打印队列元素的。

若题目要求有可以随时打印队列全部元素的功能,只能用我的解法。

猜你喜欢

转载自blog.csdn.net/qq_43799400/article/details/131158486