💬 前言
本文主要是记录我在Leetcode上对题号232——栈实现队列的解题过程。
🔑 要求
请你仅使用两个栈实现先入先出队列。队列应当支持一般队列的支持的所有操作(push
、pop
、peek
、empty
):
实现 MyQueue 类:
void push(int x)
将元素x
推到队列的末尾int pop()
从队列的开头移除并返回元素int peek()
返回队列开头的元素boolean empty()
如果队列为空,返回true
;否则,返回false
思路:双栈实现队列
核心思想:
用栈实现队列和上章的用队列实现栈的方法类似。准备两个队列,一个队列一,一个队列二,队列二用来暂时缓存队列一的元素。
在推入元素阶段时,用循环将栈倒置,把最先入的元素放在栈顶,那么第一个出栈的也就是最先入栈的元素,这样子就能达到和队列一样先入先出( FIFO )的效果。
具体实现
这里实现也没啥难的,代码不多,主要是集中在push()
方法,使用两个栈维护元素。其余方法都是复用。
import java.util.Stack;
/**
* LeetCode 题号232
* 使用栈实现队列
*
* @author FutureIsHereX
* @since 2021/2/19
*/
class MyQueue {
private Stack<Integer> stack;
public MyQueue() {
// 创建实际使用的主栈
stack = new Stack<>();
}
public void push(int x) {
// 创建缓存栈
Stack<Integer> stack2 = new Stack<>();
// 将栈里所有元素取出并缓存
while (!stack.empty()) {
stack2.push(stack.pop());
}
// 将最新加入的元素放入栈底
stack.push(x);
// 再将缓存栈里的旧元素依次放回主栈
// 这样最旧的元素总在栈顶,取出时也是最旧的元素
while (!stack2.empty()) {
stack.push(stack2.pop());
}
}
public int pop() {
return stack.pop();
}
public int peek() {
return stack.peek();
}
public boolean empty() {
return stack.empty();
}
}
复杂度分析
方法 | 具体值 | 备注 |
---|---|---|
push() | O(n) | 通过两次循环来承担倒栈的职责 |
pop() | O(1) | 复用了栈的pop() 方法 |
peek() | O(1) | 复用了栈的peek() 方法 |
empty() | O(1) | 复用了栈的empty() 方法 |
📝 总结
- 使用栈实现队列的方法与用队列实现栈的方法类似,都可以用两个相同的数据结构来维护。
- 由于栈单端开口的缘故,无法通过使用一个栈就能实现队列的效果。
- 由于Java官方不再推荐使用
Stack
类,其实栈的实现类可以替换为ArrayDeque
。