LeetCode 232. 用栈实现队列
本题是一道简单题,饶有趣味的是,本题的解法是分摊复杂度的一种典型应用。
请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(push
、pop
、peek
、empty
):
实现 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:
输入: |
提示:
1 <= x <= 9
- 最多调用
100
次push
、pop
、peek
和empty
- 假设所有操作都是有效的 (例如,一个空的队列不会调用
pop
或者peek
操作)
进阶:
- 你能否实现每个操作均摊时间复杂度为
O(1)
的队列?换句话说,执行n
个操作的总时间复杂度为O(n)
,即使其中一个操作可能花费较长时间。
思路
常规解法
我们先考虑常规解法。设两个栈分别为s1
、s2
,每次入队时,我们将元素压入s1
中,那么s1
中栈底存放的是队首元素,栈顶存放的是队尾元素。每次执行出队操作时,我们将s1
中的元素全部弹出,压入s2
中,这样s2
的栈顶元素就是队尾元素。栈顶元素出栈后,再将s2
中的元素移回s1
中。
这种方案下,元素入队操作的时间复杂度push,push,...,pop,pop
,即先执行
出入队优化
实际上,将s1
的元素移动到s2
中,执行出队操作之后,我们并不需要再将元素再次移回s1
中,只需要在下次出队时判断一下,若s2
为空,再将此时s1
中的元素全部移动到s2
中。这样就大幅减少了元素来回移动的复杂度。我们采用记账分析法,每个元素在入队时需要支付s1
移动到s2
的代价,出队操作只需支付
class MyQueue { |
复杂度
- 时间复杂度:分摊复杂度为
。 - 空间复杂度:
。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 阿日哥的向量空间!