用两个栈实现队列

image.png

题目解释

image.png

示例一:

输入"CQueue": 创建队列([此时队列[]]),所以没有数字出队列,输出null,
输入"appendTail": 加入输入中的数3到队尾(此时队列[3]),所以没有数字出队列,输出null
输入"deleteHead": 删除对头的数即把队伍中3删除(此时队列[]),所以数字3出队列,输出3
输入"deleteHead": 删除对头的数但队伍为空,输出-1

题目知识

先进后出
队列 先进先出
一个栈没办法实现先进先出,所以需要两个栈
栈A实现入队功能,栈B实现出队功能
栈A的元素1234执行出栈放到栈B变成4321(即相对倒序入栈了),然后对栈B执行出栈操作,出栈顺序1234,相当于正序出栈,对比一开始的入栈12234,就变成了先进先出

  • Deque接口 读作deck
    image.png
public interface Deque<E> extends Queue<E>

Deque 双端队列

  1. Deque的实现类有LinkedList、ArrayDeque、LinkedBlockingDeque,其中LinkedList是最常用的。

    Deque支持在两端插入和移除元素、检查元素

  2. LinkedList类

     1、可以索引、可以重复
     2、有序:存储和取出的顺序一致
  3. 普通队列(一端进另一端出)、双端队列(两端都可以进出)、堆栈的构造都能用以下方法:

    `Deque deque = new LinkedList()`
    

image.png

  • Queue 接口
    Queue接口使用方法
    Deque接口扩展(继承)了 Queue 接口。在将双端队列用作队列时,将得到 FIFO(先进先出)行为。将元素添加到双端队列的末尾,从双端队列的开头移除元素。从 Queue 接口继承的方法完全等效于 Deque 方法,如下表所示:
    image.png

    题目解读

  • 加入队尾元素:加入队尾 appendTail()函数,也就是只需要把元素val加入栈A做入栈操作即可
  • 删除队首元素:删除队首deleteHead()函数
    分情况讨论

    • 如果栈B不为空,那就说明栈B里面已经有元素做好了出栈(相等于出队列的操作)的准备,那就可以直接对栈B执行出栈操作,就把队首元素删除了
    • 如果栈B为空,栈A不为空,就说明还有元素没有进入倒序,那就需要把A元素全部放入B中,实现元素倒序,再执行出栈操作
    • 如果栈A和栈B都为空,那就说明队列里没有元素,那就是返回-1
  1. 一开始栈A和栈B都为空,返回-1
  2. 然后执行入栈操作入元素5,然后又将元素2入栈
  3. 然后执行delete操作,发现栈B空,A不空,此时对A出栈B入栈(倒序操作)栈B就是25,然后再执行B出栈删除队首元素,返回元素5
  4. 然后继续执行delete操作,发现栈B不空,那直接对B出栈,返回元素2

    题解

    public CQueue():创建对象,需要把两个栈声明为CQueue类的全局变量。
    public void appendTail(int value):直接push到栈1
    public int deleteHead():目前栈1就是所有元素,再pop到栈2,那么栈2再pop就是头元素。(如果栈2没有元素,才能pop到栈2,否则顺序不对)
    image.png

    答案

    image.png


Loccy
4 声望1 粉丝