本文整理来源 《轻松学算法——互联网算法面试宝典》/赵烨 编著面试
因为栈和队列的特殊顺序存储结构,一些面试官会出一些题目,好比用栈实现队列和用队列实现栈。算法
这样的题目在实际工做中并不具备实际应用意义,彻底是为了考察你们的思考能力。测试
通常会用两个栈来实现队列。首先,咱们将这两个栈分别定义为stack1和stack2code
方案1
咱们让入队操做在stack1中执行,而出队操做在stack2中执行。队列
来回入栈、出队比较繁琐,尤为是出队比较麻烦,须要先将元素从stack1倒入stack2里,而后stack2弹出元素以后又倒回stack1里。ci
方案2
入队都在stack1中进行,stack2用于出队,同时保证全部元素都在一个栈里,且遵循如下规则:it
这种思路与方案1同样,只不过把倒回去的这个操做放在入队时执行,却使连续入队、出队的效率提升了。io
方案3
入队都在stack1中操做,出队在stack2中操做,同时遵循如下规则:class
这个方案在入队时很是简单,而在出队时,多数状况下能够直接经过出队stack2实现,若须要把stack1中的元素倒入stack2中,则通常不用每次都进行操做。最坏的状况就是出队一个元素、入队一个元素这样循环操做,致使每次出队都要转移元素。效率
三个方案的操做时同样的。整体来讲方案3是很是好的方案。
public class Stack2Queue<T> { private Stack<T> stack1; private Stack<T> stack2; private int maxLength; public Stack2Queue(int capacity) { maxLength = capacity; stack1 = new Stack<>(capacity); stack2 = new Stack<>(capacity); } public boolean put(T item){ if (stack1.isFull() || maxLength == size()){ //满了 return false; } stack1.push(item); return true; } public T poll(){ if (!stack2.isEmpty()){ return stack2.pop(); }else { while (!stack1.isEmpty()){ stack2.push(stack1.pop()); } return stack2.pop(); } } private int size() { return stack1.size() + stack2.size(); } }
测试代码:
public class Stack2QueueTest { @Test public void main(){ Stack2Queue<Integer> queue = new Stack2Queue<>(5); queue.put(1); queue.put(2); Assert.assertEquals(1,(int)queue.poll()); queue.put(3); queue.put(4); Assert.assertEquals(2,(int)queue.poll()); Assert.assertEquals(3,(int)queue.poll()); } }
栈的主要操做就是入栈和出栈,其特色就是后进先出。
咱们先将两个队列分别定义为queue1与queue2。
方案1
入栈和出栈,都是queue1中完成,而queue2做为中转空间
这种操做过程与用栈实现队列的方案1同样,都是把第2个结构当作一个中转站,而后将数据来回倒。
方案2
从方案1中能够看到,在出栈时要把queue2中的元素移动到queue1中。在两个队列之间可否不用每次先出栈再把元素移动回去?
public class Queue2Stack<T> { private ArrayQueue<T> queue1; private ArrayQueue<T> queue2; private int maxLength; public Queue2Stack(int capacity){ maxLength = capacity; queue1 = new ArrayQueue<>(capacity); queue2 = new ArrayQueue<>(capacity); } /** * 入栈 * @param item 入栈元素 * @return 入栈结果 */ public boolean push(T item){ if(size() == maxLength){ return false; } //若是中转空间为空,能够直接放入。当须要出栈时,放入元素即为队头 if (queue2.isEmpty()){ queue1.put(item); }else { queue2.put(item); } return true; } /** * 出栈 * @return 出栈元素 */ public T pop(){ if (size() == 0){ throw new IndexOutOfBoundsException("栈里空了"); }else { if (queue2.isEmpty()){ while (queue1.size() > 1){ queue2.put(queue1.poll()); } return queue1.poll(); }else { while (queue2.size() > 1){ queue1.put(queue2.poll()); } return queue2.poll(); } } } private int size() { return queue1.size() + queue2.size(); } }
测试代码:
public class Queue2StackTest { @Test public void main() { Queue2Stack<Integer> stack = new Queue2Stack<>(5); stack.push(1); stack.push(2); Assert.assertEquals(2, (int) stack.pop()); stack.push(3); stack.push(4); Assert.assertEquals(4, (int) stack.pop()); Assert.assertEquals(3, (int) stack.pop()); } }