本文整理來源 《輕鬆學算法——互聯網算法面試寶典》/趙燁 編著面試
因爲棧和隊列的特殊順序存儲結構,一些面試官會出一些題目,好比用棧實現隊列和用隊列實現棧。算法
這樣的題目在實際工做中並不具備實際應用意義,徹底是爲了考察你們的思考能力。測試
通常會用兩個棧來實現隊列。首先,咱們將這兩個棧分別定義爲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()); } }