栈的特点是后进先出,队的特点是先进先出。今天我们学习的内容是用栈实现队和用队实现栈。
232. 用栈实现队列
https://leetcode.cn/problems/implement-queue-using-stacks/
一、LeetCode232.用栈实现队列
请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(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:
输入: ["MyQueue", "push", "push", "peek", "pop", "empty"] [[], [1], [2], [], [], []] 输出: [null, null, null, 1, 1, false]
思路:题目给了我们两个栈使用,我们一个用来存数据(push),另一个用来显示(peek)和弹出(pop)。当需要peek和pop的时候,就将栈一中的元素全部push到栈二当中。
所以代码中的 in2out()函数是关键~
画了图帮助理解

上代码
class MyQueue { // 定义一个名为MyQueue的类
Deque<Integer> inStack; // 定义一个Deque类型的成员变量inStack,用于存储进入队列的元素
Deque<Integer> outStack; // 定义一个Deque类型的成员变量outStack,用于存储从队列中取出的元素
public MyQueue() { // 定义MyQueue的构造函数
inStack = new LinkedList<Integer>(); // 使用LinkedList实现Deque,初始化inStack
outStack = new LinkedList<Integer>(); // 使用LinkedList实现Deque,初始化outStack
}
public void push(int x) { // 定义一个push方法,用于将元素x入队
inStack.push(x); // 将x添加到inStack的尾部
}
public int pop() { // 定义一个pop方法,用于取出队列中的元素
if (outStack.isEmpty()) { // 如果outStack为空,即队列中没有可取出的元素
in2out(); // 将inStack中的元素全部转移到outStack中,保证最先进入队列的元素在最前面
}
return outStack.pop(); // 返回并移除outStack的尾部元素,即队列中的第一个元素
}
public int peek() { // 定义一个peek方法,用于查看队列中的第一个元素但不取出
if (outStack.isEmpty()) { // 如果outStack为空,即队列中没有可查看的元素
in2out(); // 将inStack中的元素全部转移到outStack中,保证最先进入队列的元素在最前面
}
return outStack.peek(); // 返回并查看outStack的尾部元素,即队列中的第一个元素但不取出
}
public boolean empty() { // 定义一个empty方法,用于判断队列是否为空
return inStack.isEmpty() && outStack.isEmpty(); // 如果inStack和outStack都为空,则队列为空
}
private void in2out() { // 定义一个私有方法in2out,用于将inStack中的元素转移到outStack中
while (!inStack.isEmpty()) { // 当inStack不为空时
outStack.push(inStack.pop()); // 将inStack的元素弹出并添加到outStack中
}
}
}
二、LeetCode225.用队列实现栈
请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(push、top、pop 和 empty)。
实现 MyStack 类:
void push(int x)将元素 x 压入栈顶。int pop()移除并返回栈顶元素。int top()返回栈顶元素。boolean empty()如果栈是空的,返回true;否则,返回false。
注意:
- 你只能使用队列的基本操作 —— 也就是
push to back、peek/pop from front、size和is empty这些操作。 - 你所使用的语言也许不支持队列。 你可以使用 list (列表)或者 deque(双端队列)来模拟一个队列 , 只要是标准的队列操作即可。
示例:
输入: ["MyStack", "push", "push", "top", "pop", "empty"] [[], [1], [2], [], [], []] 输出: [null, null, null, 2, 2, false] 解释: MyStack myStack = new MyStack(); myStack.push(1); myStack.push(2); myStack.top(); // 返回 2 myStack.pop(); // 返回 2 myStack.empty(); // 返回 False
思路:
入栈操作时,首先将元素入队到 queue2,然后将 queue1的全部元素依次出队并入队到queue2,此时 queue2的前端的元素即为新入栈的元素,再将 queue1和queue2互换,则 queue1的元素即为栈内的元素,queue 1的前端和后端分别对应栈顶和栈底。
由于每次入栈操作都确保queue1的前端元素为栈顶元素,因此出栈操作和获得栈顶元素操作都可以简单实现。出栈操作只需要移除queue1的前端元素并返回即可,获得栈顶元素操作只需要获得 queue 1的前端元素并返回即可(不移除元素)。
由于 queue 1用于存储栈内的元素,判断栈是否为空时,只需要判断 queue1是否为空即可。
画图理解
两个队列,都只能从上面出,下面入

代码如下
// 定义一个名为MyStack的类
class MyStack {
// 声明两个队列,用于实现栈的操作。队列在Java中通常使用Queue接口和LinkedList实现。
Queue<Integer> queue1;
Queue<Integer> queue2;
// 定义构造函数,初始化两个队列
public MyStack() {
// 使用LinkedList实现Queue,初始化queue1
queue1 = new LinkedList<Integer>();
// 使用LinkedList实现Queue,初始化queue2
queue2 = new LinkedList<Integer>();
}
// 定义push方法,用于向栈中添加元素
public void push(int x) {
// 将元素x添加到queue2的尾部
queue2.offer(x);
// 只要queue1不为空,就将其中的元素全部移除并添加到queue2中
while (!queue1.isEmpty()) {
queue2.offer(queue1.poll());
}
// 临时交换queue1和queue2的引用,为了保持queue1始终是“空的”那个队列
Queue<Integer> temp = queue1;
queue1 = queue2;
queue2 = temp;
}
// 定义pop方法,用于从栈中取出并移除元素
public int pop() {
// 移除并返回queue1的第一个元素(栈顶元素)
return queue1.poll();
}
// 定义top方法,用于查看栈顶元素但不移除它
public int top() {
// 查看(但不移除)queue1的第一个元素(栈顶元素)
return queue1.peek();
}
// 定义empty方法,用于判断栈是否为空
public boolean empty() {
// 检查queue1是否为空,如果为空则返回true,否则返回false
return queue1.isEmpty();
}
}
栈队列模拟:LeetCode中的数据结构应用,
文章探讨了如何使用栈和队列数据结构解决LeetCode中的232题(用栈实现队列)和225题(用队列实现栈),涉及push、pop、peek和empty操作的实现策略。
244

被折叠的 条评论
为什么被折叠?



