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(双端队列)来模拟一个栈,只要是标准的栈操作即可。
题目链接:232. 用栈实现队列
卡哥的视频链接:栈的基本操作! | LeetCode:232.用栈实现队列
栈是一种仅支持在表尾进行插入和删除操作的线性表,这一端被称为栈顶,另一端被称为栈底。元素入栈指的是把新元素放到栈顶元素的上面,使之成为新的栈顶元素;元素出栈指的是从一个栈删除元素又称作出栈或退栈,它是把栈顶元素删除掉,使其相邻的元素成为新的栈顶元素。栈中的元素遵守后进先出(LIFO)的原则.
栈的底层有两种:分别是基于数组的顺序栈和基于链表的链式栈
解题思路:定义两个栈,一个入栈一个出栈,由于队列是先进先出的,要想通过栈实现,我们可以再定义一个栈,把输入栈的元素再通过输出栈重新输出,顺序就会和队列一模一样
代码示例:
import java.util.Stack;public class zhan_duilie {//声明两个栈private Stack <Integer>A;private Stack <Integer>B;//构造方法,用来初始化两个新栈public zhan_duilie() {A = new Stack<>();B = new Stack<>();}
//把x元素压入A栈中,A用于入栈,B用于出栈public void push(int x) {A.push(x);}public int pop() {int peek = peek(); // 调用peek()方法获取队头元素B.pop(); // 从B栈中弹出元素,模拟队列的出队操作return peek; // 返回队头元素的值}public int peek() {// 如果B栈不为空,直接返回B栈顶元素,即队头元素if (!B.isEmpty()) {return B.peek();}// 如果B栈为空,但A栈也为空,则队列为空,返回-1if (A.isEmpty()) {return -1;}// 如果B栈为空,但A栈不为空,则将A栈的所有元素依次弹出并压入B栈,直到A栈为空while (!A.isEmpty()) {B.push(A.pop());}// 返回B栈顶元素,即队头元素return B.peek();}public boolean empty() {// 如果A栈和B栈都为空,则队列为空return A.isEmpty() && B.isEmpty();}
}
代码逻辑详解:
-
初始化两个栈:
在构造方法中,我们创建了两个栈,
A
和B
,用来模拟队列。 -
入队操作:
当需要入队时,我们将元素压入栈
A
中。 -
出队操作:
出队操作需要确保队列的先进先出原则。我们先检查栈
B
是否为空,如果不为空,直接从B
栈中弹出元素;如果B
栈为空,我们将栈A
的元素依次弹出并压入B
栈,然后再从B
栈中弹出元素,确保了队列的先进先出顺序。 -
获取队头元素:
我们首先检查栈
B
是否为空,如果不为空,直接返回B
栈顶元素;如果B
栈为空,我们将栈A
的元素依次弹出并压入B
栈,然后返回B
栈顶元素,即为队头元素。 -
判断队列是否为空:
我们只需检查两个栈是否都为空,若都为空则队列为空。
通过这些步骤,我们用两个栈实现了队列的基本功能,包括入队、出队、获取队头元素和判断队列是否为空。
leetcode提交记录:
小tips:
1.在队列中,出队操作应该返回队头元素,并将其从队列中移除。因此,在执行出队操作之前,我们需要先获取队头元素的值,以便在之后返回。否则,如果直接执行出队操作,我们就无法获取到出队的元素是什么,无法返回其值。
2.注意栈的定义和方法的具体使用
225.用队列实现栈
题目:
请你仅使用两个队列实现一个后入先出(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
提示:
1 <= x <= 9
- 最多调用
100
次push
、pop
、top
和empty
- 每次调用
pop
和top
都保证栈不为空
题目链接:225. 用队列实现栈
卡哥的视频链接:队列的基本操作! | LeetCode:225. 用队列实现栈
题目思考:因为队列就像一个管道,怎么进去就怎么出来,所以我们要用两个队列,其中一个负责输出,一个负责储存,这样才能模拟实现栈的功能。
代码示例:
import java.util.LinkedList;
import java.util.Queue;public class duilie_zhan {// 声明两个队列作为栈的辅助数据结构Queue<Integer> queue1 = new LinkedList<>();Queue<Integer> queue2 = new LinkedList<>();// 构造方法,初始化两个队列public duilie_zhan() {queue1 = new LinkedList<>();queue2 = new LinkedList<>();}// 入栈操作public void push(int x) {// 将新元素添加到队列2的末尾queue2.offer(x);// 将队列1的元素逐个出队并添加到队列2的末尾,确保新入栈的元素位于栈的顶部while (!queue1.isEmpty()) {queue2.offer(queue1.poll());}// 交换队列1和队列2,保持队列1始终为当前栈的主队列Queue<Integer> queueTemp;queueTemp = queue1;queue1 = queue2;queue2 = queueTemp;}// 获取栈顶元素public int top() {// 返回队列1的头部元素,即栈顶元素return queue1.peek();}// 判断栈是否为空public boolean empty() {// 如果队列1为空,则栈为空return queue1.isEmpty();}
}
代码逻辑详解:
-
入栈操作:
- 当执行入栈操作时,首先将新元素加入到一个辅助队列中(这里是
queue2
)。 - 然后,我们需要确保新入栈的元素位于栈顶,因此将主队列(这里是
queue1
)中的所有元素逐个出队,并依次加入到辅助队列的末尾。 - 最后,为了保持栈的逻辑顺序,我们将主队列和辅助队列的引用进行交换,使得主队列成为当前栈的主队列。
- 当执行入栈操作时,首先将新元素加入到一个辅助队列中(这里是
-
获取栈顶元素:
- 获取栈顶元素的操作是非常简单的,只需要返回主队列(这里是
queue1
)的头部元素即可,因为头部元素即为栈顶元素。
- 获取栈顶元素的操作是非常简单的,只需要返回主队列(这里是
- 判断栈是否为空:
- 要判断栈是否为空,只需要检查主队列(
queue1
)是否为空即可。如果主队列为空,则表示栈为空。
- 要判断栈是否为空,只需要检查主队列(
总的来说,这段代码实现了使用两个队列来模拟栈的功能。在入栈操作中,我们使用了一个辅助队列来保持栈顺序的正确性,并且在需要时交换了主队列和辅助队列的引用。通过这种方式,我们可以利用队列的先进先出特性来模拟栈的后进先出行为。
leetcode提交记录:
小tips:
1.因为queue1是主队列,存储的全部的元素,所以取顶部元素、弹出元素和判断空都只需要对queue1进行操作
2.在对queue2进行添加新元素,把queue1的元素放入queue2中后,为了保证逻辑正确,我们要交换两个队列
3.注意队列的定义,没有圆括号,尖括号中要表明数据类型