面试题:两个队列实现一个栈
面试中,经常出现让你手写两个队列实现一个栈,或者两个栈实现一个队列的问题,很是头疼!
我们在前一篇米扑博客介绍了:两个栈实现一个队列
今天我们先探讨下:两个队列如何实现一个栈?
一、栈的特性
1、先进后出
2、进出都在栈顶
3、栈的实现有数组、链表
4、栈的应用场景有递归、深度遍历、函数名参数压栈等
二、队列的特性
1、先进先出
2、进在队尾,出在队头
3、队列的实现有数组、链表
4、队列的应用场景有消息队列、层次遍历等
三、两个栈实现一个队列
若用两个栈实现一个队列,思路如下:
Java 代码实现:
import java.util.Stack; public class Stack2Queue { Stack<Integer> stack1 = new Stack<Integer>(); Stack<Integer> stack2 = new Stack<Integer>(); public void push(int node) { stack1.push(node); } public int pop() { if(stack2.size()<=0){ while(stack1.size()>0){ /*int data = stack1.peek();//查看栈顶元素,但不移除它 stack1.pop();//弹出栈顶元素 stack2.push(data);//压入 */ stack2.push(stack1.pop()); } } if(stack2.isEmpty()){ try { throw new Exception("queue is empty."); } catch (Exception e) { } } /** * int head = stack2.peek(); * stack2.pop(); */ int head = stack2.pop(); return head; } }
详见米扑博客:两个栈实现一个队列
四、两个队列实现一个栈
如上图,注意两个队列的元素切换,解题思路:
1、 一个队列加入元素,弹出元素时,需要把队列中的元素转移放到另外一个队列中,删除最后一个元素
2、 两个队列始终保持只有一个队列是有数据,每次删除栈顶元素时,都需要转移一次队列的前(n-1)个元素
Java 代码实现(一):
import java.util.ArrayDeque; import java.util.Queue; public class Queue2Stack { Queue<Integer> queue1 = new ArrayDeque<>(); Queue<Integer> queue2 = new ArrayDeque<>(); public void push(int node) { // 两个栈都为空时,优先考虑queue1 if (queue1.isEmpty() && queue2.isEmpty()) { queue1.add(node); return; } // 如果queue1为空,queue2有元素,直接放入queue2 if (queue1.isEmpty()) { queue2.add(node); return; } if (queue2.isEmpty()) { queue1.add(node); return; } } public int pop() { // 两个栈都为空时,没有元素可以弹出 if (queue1.isEmpty() && queue2.isEmpty()) { try { throw new Exception("stack is empty"); } catch (Exception e) { } } // 如果queue1为空,queue2有元素, 将queue2的元素依次放入queue1中,直到最后一个元素,我们弹出。 if (queue1.isEmpty()) { while (queue2.size()>1) { queue1.add(queue2.poll()); } return queue2.poll(); } if (queue2.isEmpty()) { while (queue1.size()>1) { queue2.add(queue1.poll()); } return queue1.poll(); } return (Integer) null; } public static void main(String[] args) { Queue2Stack stack = new Queue2Stack(); stack.push(1); stack.push(2); stack.push(3); stack.push(4); System.out.println(stack.pop()); System.out.println(stack.pop()); stack.push(5); System.out.println(stack.pop()); System.out.println(stack.pop()); System.out.println(stack.pop()); } }
Java 代码实现(二):
import java.util.LinkedList; import java.util.Queue; /** * 两个队列实现一个栈 * 1、一个队列加入元素,弹出元素时,需要把队列中的元素转移放到另外一个队列中,删除最后一个元素 * 2、两个队列始终保持只有一个队列是有数据,每次删除栈顶元素时,都需要转移一次队列的前(n-1)个元素 */ public class StackByQueue<T> { private Queue<T> queue1 = new LinkedList<>(); private Queue<T> queue2 = new LinkedList<>(); // 压栈,入栈非空的队列 public boolean push(T t) { /* // 此写法不严谨, 若queue2不为空, 应该向queue2队尾添加新元素, 此处判断不可以偷懒 if (!queue1.isEmpty()) { return queue1.offer(t); } else { return queue2.offer(t); } */ // 正确的严谨写法 if (queue1.isEmpty() && queue2.isEmpty()) { return queue1.offer(t); } else if (queue1.isEmpty()) { return queue2.offer(t); } else if (queue2.isEmpty()) { return queue1.offer(t); } } // 弹出并删除元素 public T pop() { if (queue1.isEmpty() && queue2.isEmpty()) { throw new RuntimeException("queue is empty"); } if (!queue1.isEmpty() && queue2.isEmpty()) { while (queue1.size() > 1) { // 保留队列的最后一个(队尾)元素 queue2.offer(queue1.poll()); } return queue1.poll(); } if (queue1.isEmpty() && !queue2.isEmpty()) { while (queue2.size() > 1) { // 保留队列的最后一个(队尾)元素 queue1.offer(queue2.poll()); } return queue2.poll(); } return null; } @Override public String toString() { return this.queue1.toString() + ", " +this.queue2.toString(); } // 主函数 public static void main(String[] args) { StackByQueue<Integer> stack = new StackByQueue<>(); stack.push(1); stack.push(2); stack.push(3); stack.pop(); System.out.println(stack); stack.push(4); stack.push(5); stack.pop(); System.out.println(stack); } }
参考推荐:
LeetCode 543. 二叉树的直径 (任意两结点最长距离)
LeetCode 206 反转链表 (推荐先看)
LeetCode 2. 两链表整数相加生成一个和的新链表(含变异改进算法)
版权所有: 本文系米扑博客原创、转载、摘录,或修订后发表,最后更新于 2021-03-04 05:15:26
侵权处理: 本个人博客,不盈利,若侵犯了您的作品权,请联系博主删除,莫恶意,索钱财,感谢!
转载注明: 面试题:两个队列实现一个栈 (米扑博客)