算法面試:棧實現隊列的方案

聲明:碼字不易,轉載請註明出處,歡迎文章下方討論交流。

前言:Java數據結構與算法專題會不定時更新,歡迎各位讀者監督。本篇文章介紹一個有趣的問題:用兩個棧實現一個隊列。這道題來自互聯網公司的算法面試,做爲一道經典的算法面試題,本文給出問題的解決思路和Java實現代碼。java

前兩篇文章介紹了棧(stack)隊列(queue)兩種特殊的數據結構和他們特色,棧和隊列雖然是特色針鋒相對的,但有意思的是他們卻彼此相互聯繫。面試

後進先出的棧如何才能實現先進先出的隊列呢?通常會用兩個棧來實現。首先定義兩個棧分別爲stack1和stack2.算法

1.解決方案一:

咱們讓入隊的操做在stack1中完成,出隊的操做在stack2中完成,具體分析過程以下:segmentfault

  • 入隊: ①將全部元素直接向stack1中壓棧
  • 出隊: ②將stack1中的全部元素依次出棧,③緊接着入棧到stack2中,④而後彈出stack2中的元素。

爲清楚說明,用下圖解釋:
圖片描述
來回入隊、出隊比較麻煩,尤爲是出隊比較麻煩,須要先將元素從stack1倒入stack2中,而後stack2彈出的元素又倒回到stack1中。有沒有更優化的方案呢?如下方案2是改進以後的思路。數據結構

2.解決方案二:

入隊都在stack1中進行,stack2用於隊列,同時保證全部元素都在一個棧裏,且遵循如下約束:測試

  • 入隊:無論stack1空與否,都將stack2中的全部元素壓入stack1中
  • 出隊:若stack2中不爲空,則直接從stack2中彈出元素;若stack2爲空,則說明隊列爲空,不能出隊。

方案2與方案1的區別在於,方案2中把倒回的操做放在了入隊中完成,使連續入隊、出隊的效率提升。有沒有更優化的方案呢?如下對方案2改進,給出方案3.優化

3.解決方案三:

入隊都在stack1中完成,出隊都在stack2中完成,且遵循如下約束:spa

  • 入隊:直接把元素壓入stack1中;
  • 出隊:若stack2中不爲空,則直接彈出stack2中的元素;若stack2中爲空,則將stack1中的全部元素倒入stack2中,而後彈出stack2的棧頂元素。一樣,若兩個棧都爲空,則隊列爲空隊,沒法出隊。

方案3的特色是:入隊時很是簡單,而在出隊時,多數狀況下能夠直接經過彈出stack2完成。若是把stack1中的元素倒入stack2中,則通常不用每次都進行這樣的操做。最壞的狀況就是出隊一個元素、入隊一個元素這樣的循環,致使每次出隊都須要轉移元素。code

4.java代碼實現

如下給出方案3的代碼實現:隊列

public class Stacks2Queue {
    private Stack stack1;
    private Stack stack2;
    private int maxLength;
    
    public Stacks2Queue(int capacity){
        maxLength = capacity;
        stack1 = new Stack(capacity);        
        stack2 = new Stack(capacity);        
    }
    
    /**
     * 隊列入隊
     * @param element 入隊元素
     * @return 入隊成功?
     */
    public boolean put(int element){
        if(stack1.isFull() || maxLength == stack1.getSize()){
            //此時stack1滿
            return false;
        }
        stack1.push(element);
        return true;
    }
    
    /**
     * 隊列出隊
     * @return 出隊的元素
     */
    public int poll(){
        if(!stack2.isEmpty()){
            return stack2.pop();
        }else{
            while(!stack1.isEmpty()){
                stack2.push(stack1.pop());
            }return stack2.pop();
        }
    }
    
    /**
     * 求隊列長度
     * @return 返回隊列長度
     */
    public int getSize(){
        return stack1.getSize()+stack2.getSize();
    }
}

測試代碼以下:

public class Stack2QueueTest {
    public static void main(String[] args) {
        Stacks2Queue q = new Stacks2Queue(5);
        q.put(1);   //入隊元素 1
        q.put(2);   //入隊元素 2
        System.out.println("出隊的元素爲"+q.poll());   //出隊元素   打印1
        System.out.println("此時隊列長度爲"+q.getSize());  //返回1
        q.put(3);   //入隊元素 3
        q.put(4);   //入隊元素 4
        System.out.println("出隊的元素爲"+q.poll());   //出隊元素  打印2
        System.out.println("出隊的元素爲"+q.poll());   //出隊元素  打印3 本次出隊操做會把3和4兩個元素從stack1中倒入stack2中
    }
}

注:以上代碼用到了堆和棧的代碼,請移步到前兩篇文章獲取Java數據結構與算法——棧(stack)Java數據結構與算法——隊列(queue)

5.小結:

本文介紹了一個互聯網面試經典問題如何用兩個棧實現隊列?並給出解決思路和java代碼實現,後續會給出其姊妹篇如何用兩個隊列實現棧?的問題。

歡迎下方討論提問,以爲文章對您有用,請收藏點個贊 ^_^

相關文章
相關標籤/搜索