题目描述


题目地址:https://leetcode-cn.com/problems/yong-liang-ge-zhan-shi-xian-dui-lie-lcof/

用两个栈实现一个队列。

队列的声明如下:请实现它的两个函数 appendTail 和 deleteHead ,分别完成在队列尾部插入整数和在队列头部删除整数的功能。(若队列中没有元素,deleteHead 操作返回 -1 )

  1. 输入:
  2. ["CQueue","appendTail","deleteHead","deleteHead"]
  3. [[],[3],[],[]]
  4. 输出:[null,null,3,-1]

解题思路


K神题解:https://leetcode-cn.com/problems/yong-liang-ge-zhan-shi-xian-dui-lie-lcof/

LinkedList 底层是双向链表,既可以用作栈也可以用作队列,所以用 LinkedList 来模拟栈是可以的

addLast( ) 表示向链表尾部插入元素,等价于向栈顶插入元素;
removeLast ( ) 表示从链表尾部取出元素,等价于从栈顶取出元素。

  • A 和 B 都可以在某一个时刻存储着队列的所有元素,取决于添加元素和删除队首元素的方法执行了没有:
  • 一开始,如果只是添加元素,那就只有栈 A 保存着所有的元素;
  • 这时一旦调用了一次删除队首元素,那么原先在栈 A 的所有元素都会以倒序的顺序搬到栈 B ,然后栈 B 的栈顶元素出栈,实现删除队首元素;
  • 这时候栈 B 中的剩余元素不用再重新搬回到栈 A 中,因为此时队列的功能并没有被破坏;比如这时若要在队列尾增加元素,就相当于在空的栈 A 中添加元素,功能完全不受影响;而此时的栈 B 是存在元素的,此刻的栈 A 并不能以倒序的方式加到栈 B 中,而是要先等到栈 B 的所有元素都出栈后,栈 A 的元素才可以倒序进入到栈 B(体现在代码中就是在删除队首元素的方法中首先判断 B 栈是否为空,而不能先将栈 A 的元素倒序搬到栈 B 中!)
  • 所以说栈 A 和栈 B 可以同时存储着数据来表示队列,只要队列的功能不受破坏就行了!

  • 核心是栈 A 实现在队尾添加元素,栈 B 实现删除队首元素并返回;而在栈 B 删除队首元素的同时,若栈 B 还有元素,则在执行删除队首元素方法的时候,不会将栈 A 还有的元素搬到栈 B 中,而是先执行了将栈 B 栈顶的元素出栈实现删除队首元素并结束方法;直到等到栈 B 为空时,在执行删除队首元素的方法的时候才会将栈 A 的元素倒序搬到栈 B 中。

09. 用两个栈实现队列 - 图1

  1. class CQueue {
  2. Stack<Integer> A,B;
  3. public CQueue() {
  4. A = new Stack<>();
  5. B = new Stack<>();
  6. }
  7. public void appendTail(int value) {
  8. A.add(value);
  9. }
  10. public int deleteHead() {
  11. if(!B.empty()) return B.pop();
  12. if(A.empty()) return -1;
  13. while(!A.empty()){
  14. B.add(A.pop());
  15. }
  16. return B.pop();
  17. }
  18. }
  1. // 用 LinkedList 模拟栈
  2. LinkedList<Integer> A, B;
  3. public CQueue() {
  4. A = new LinkedList<Integer>();
  5. B = new LinkedList<Integer>();
  6. }
  7. public void appendTail(int value) {
  8. A.addLast(value);
  9. }
  10. public int deleteHead() {
  11. if(!B.isEmpty()) return B.removeLast();
  12. if(A.isEmpty()) return -1;
  13. if(B.isEmpty()) {
  14. while(!A.isEmpty()) {
  15. B.addLast(A.removeLast());
  16. }
  17. }
  18. return B.removeLast();
  19. }