题目难度: 简单
今天继续更新程序员面试金典系列, 大家在公众号 算法精选 里回复 面试金典 就能看到该系列当前连载的所有文章了, 记得关注哦~
题目描述
实现一个 MyQueue 类,该类用两个栈来实现一个队列。
示例:
MyQueue queue = new MyQueue();
queue.push(1);
queue.push(2);
queue.peek(); // 返回 1
queue.pop(); // 返回 1
queue.empty(); // 返回 false
说明:
- 你只能使用标准的栈操作 – 也就是只有 push to top, peek/pop from top, size 和 is empty 操作是合法的。
- 你所使用的语言也许不支持栈。你可以使用 list 或者 deque(双端队列)来模拟一个栈,只要是标准的栈操作即可。
- 假设所有操作都是有效的 (例如,一个空的队列不会调用 pop 或者 peek 操作)。
题目思考
- 如何操作两个栈来模拟队列顺序?
解决方案
思路
- 使用两个栈: 一个作为 push 的输入栈, 存正常的元素插入顺序; 另一个作为队列的输出栈, 存元素插入顺序的逆序, 这样输出栈的顶就是队列的头
- push 时: 直接 push 到输入栈即可
- pop 和 peek 时: 如果输出栈还有元素, 则直接用它的顶; 否则将当前输入栈的元素倒入输出栈中, 然后再用输出栈的顶
复杂度
- 时间复杂度 O(1): 显然 push 和 empty 操作是 O(1), 而虽然 pop 和 peek 有可能涉及两个栈元素的移动, 但每个元素最多被操作两次 (一次是加入到输入栈, 一次是移动到输出栈), 所以均摊下来它们的时间复杂度也为 O(1)
- 空间复杂度 O(N): 使用了两个栈存 N 个元素
代码
class MyQueue:
def __init__(self):
"""
Initialize your data structure here.
"""
# 初始化输入栈和输出栈
self.stackIn = []
self.stackOut = []
def push(self, x: int) -> None:
"""
Push element x to the back of queue.
"""
# 直接追加到输入栈
self.stackIn.append(x)
def pop(self) -> int:
"""
Removes the element from in front of queue and returns that element.
"""
if self.empty():
# 没有元素, pop返回-1
return -1
res = self.peek()
# 此时直接pop输出栈即可, peek的时候已经做好了栈的转移
self.stackOut.pop()
return res
def peek(self) -> int:
"""
Get the front element.
"""
if self.empty():
# 没有元素, peek返回-1
return -1
if self.stackOut:
# 如果逆序的输出栈还有元素, 栈顶即为队列头
return self.stackOut[-1]
else:
# 此时需要将输入栈的元素逆序倒入输出栈中, 然后仍返回输出栈的栈顶
while self.stackIn:
self.stackOut.append(self.stackIn.pop())
return self.stackOut[-1]
def empty(self) -> bool:
"""
Returns whether the queue is empty.
"""
# 如果两个栈都没有元素, 则队列为空
return not self.stackIn and not self.stackOut
大家可以在下面这些地方找到我~😊
我的公众号: 算法精选, 欢迎大家扫码关注~😊