用两个队列实现一个栈的关键在于如何利用队列的先进先出(FIFO)特性来模拟栈的后进先出(LIFO)特性。我们可以通过以下两种方法之一来实现:
-
使用一个主队列和一个辅助队列:
push(x)
操作时,将新元素添加到主队列中。pop()
操作时,将主队列中的元素逐个移动到辅助队列中,直到只剩下一个元素在主队列中。然后弹出这个元素。之后交换主队列和辅助队列的角色。
-
保持主队列的倒序排列:
push(x)
操作时,将新元素添加到辅助队列,然后将主队列中的所有元素移到辅助队列,再交换主队列和辅助队列。pop()
操作时,直接从主队列弹出元素即可。
下面是第二种方法的实现代码:
import java.util.LinkedList;
import java.util.Queue;
public class MyStack {
private Queue<Integer> queue1;
private Queue<Integer> queue2;
public MyStack() {
queue1 = new LinkedList<>();
queue2 = new LinkedList<>();
}
// Push element x onto stack
public void push(int x) {
queue2.offer(x);
while (!queue1.isEmpty()) {
queue2.offer(queue1.poll());
}
Queue<Integer> temp = queue1;
queue1 = queue2;
queue2 = temp;
}
// Removes the element on top of the stack and returns that element
public int pop() {
if (queue1.isEmpty()) {
throw new RuntimeException("Stack is empty");
}
return queue1.poll();
}
// Get the top element
public int top() {
if (queue1.isEmpty()) {
throw new RuntimeException("Stack is empty");
}
return queue1.peek();
}
// Returns whether the stack is empty
public boolean empty() {
return queue1.isEmpty();
}
public static void main(String[] args) {
MyStack stack = new MyStack();
stack.push(1);
stack.push(2);
System.out.println(stack.top()); // 输出: 2
System.out.println(stack.pop()); // 输出: 2
System.out.println(stack.top()); // 输出: 1
System.out.println(stack.empty()); // 输出: false
}
}
代码解释:
- 构造方法
MyStack
:初始化两个队列queue1
和queue2
。 push(int x)
方法:- 将新元素
x
添加到queue2
中。 - 将
queue1
中的所有元素移动到queue2
中。 - 交换
queue1
和queue2
,使得queue1
始终包含最新的栈元素顺序。
- 将新元素
pop()
方法:直接从queue1
中弹出元素。top()
方法:直接获取queue1
的队首元素。empty()
方法:判断queue1
是否为空。
这种方法确保了每次 push
操作的时间复杂度为 O(n),而 pop
和 top
操作的时间复杂度为 O(1)。