leetcode 232 用栈实现队列
复习队列
-
队列是逻辑结构,底层可以用数组实现,也可以用链表实现,不同实现有不同的取舍。
-
队列也是数据结构的其中一种,和栈相反的是。队列是只允许在一端进行插入,在另一端进行删除的线性表。与栈一样,队列也是一种受限的数据结构
-
队列(Queue)是一种先进先出(FIFO - First In First Out)的数据结构
-
队列中,插入元素会发生在尾部而删除元素会发生在头部 - 先进先出原则
队列的操作
- 插入 - 在队列的尾部添加元素
- 删除 - 在队列的头部删除元素
- 查看首个元素 - 返回队列头部的元素的值
队列操作的时间复杂度
跟栈一样,队列的操作都是有效率的 -> O(1)
- 插入 - O(1)
- 删除 - O(1)
题解
思路比较简单,使用了两个栈,一个存一个取
图抄的的lucifer老师的
题目要求用栈的原生操作来实现队列,也就是说需要用到pop和push
但是我们知道pop和push都是在栈顶的操作,而队列的enque和deque则是在队列的两端的操作,这么一看一个stack好像不太能完成。
我们来分析一下过程。
假如向栈中分别 push 四个数字 1, 2, 3, 4
,那么此时栈的情况应该是

如果此时按照题目要求 pop 或者 peek的话, 应该是返回 1 才对,而 1 在栈底我们无法直接操作。如果想要返回 1,我们首先要将 2,3,4 分别出栈才行。
然而,如果我们这么做,1 虽然是正常返回了,但是 2,3,4 不就永远消失了么? 一种简答方法就是,将 2,3,4 存 起来。而题目又说了,只能使用栈这种数据结构,那么我们考虑使用一个额外的栈来存放弹出的 2,3,4。
(pop 出来不扔掉,而是存起来)
整个过程类似这样:
然而这一过程,我们也可以发生在push 阶段。
总之,就是我们需要在push 或者 pop 的时候,将数组在两个栈之间倒腾一次。
public class MyQueue {
/** Initialize your data structure here. */
private Stack<Integer> stackin=new Stack<>();//存
private Stack<Integer> stackout=new Stack<>();//取
public MyQueue() {
}
/** Push element x to the back of queue. */
public void push(int x) {
stackin.add(x);//调用push方法往存的栈里面添加元素
}
/** Removes the element from in front of queue and returns that element. */
public int pop(){
if (this.empty())throw new RuntimeException("空队列");//先判断队列是否为空,如果为空,抛出异常
if (!stackout.isEmpty())//判断取的栈是不是空的,如果不是空的直接取出来
return stackout.pop();
else {
/*如果取的栈是空的,就从存的栈中把里面的所有元素都放到取的栈中,因为我们存的时候先进的在栈底,我们把它倒入取的栈中时,原来栈底的元素就到栈顶了*/
while (!stackin.isEmpty()){
stackout.add(stackin.pop());
}
return stackout.pop();
}
}
/** Get the front element. */
public int peek() {//同pop方法,只不过不用往外弹
if (this.empty())throw new RuntimeException("空队列");
if (!stackout.isEmpty())
return stackout.peek();
else {
while (!stackin.isEmpty()){
stackout.add(stackin.pop());
}
return stackout.peek();
}
}
/** Returns whether the queue is empty. */
public boolean empty() {//当存的栈和取的栈都是空时,队列此时为空
return stackout.isEmpty()&&stackin.isEmpty();
}
}