[每日一題] 第七題:用兩個棧實現佇列

DRose發表於2020-07-31

用兩個棧實現一個佇列。佇列的宣告如下,請實現它的兩個函式 appendTail 和 deleteHead ,分別完成在佇列尾部插入整數和在佇列頭部刪除整數的功能。(若佇列中沒有元素,deleteHead 操作返回 -1 )

示例 1:

輸入:
["CQueue","appendTail","deleteHead","deleteHead"]
[[],[3],[],[]]
輸出:[null,null,3,-1]

示例 2:

輸入:
["CQueue","deleteHead","appendTail","appendTail","deleteHead","deleteHead"]
[[],[],[5],[2],[],[]]
輸出:[null,-1,null,null,5,2]

提示:

  • 1 <= values <= 10000
  • 最多會對 appendTail、deleteHead 進行 10000 次呼叫

方法一:雙棧

思路和演算法

維護兩個棧,第一個棧支援插入操作,第二個棧支援刪除操作。

根據棧先進後出的特性,我們每次往第一個棧裡插入元素後,第一個棧的底部是最後插入的元素,子一個棧的頂部元素是下一個待刪除的元素。為了維護佇列先進先出的特性,我們引入第二個棧,用第二個棧維護待刪除的元素,在執行刪除操作的時候我們首先看下第二個棧是否為空,如果未空,我們將第一個棧裡的元素一個個彈出插入到第二個棧裡,這樣第二個棧裡元素的順序就是待刪除的元素的順序,要執行刪除操作的時候我們直接彈出第二個棧的元素返回即可。

成員變數

  • 維護兩個棧 stack1stack2,其中 stack1 支援插入操作,stack2 支援刪除操作

構造方法

  • 初始化 stack1stack2 為空

插入元素

插入元素對應方法 appendTail

  • stack1 直接插入元素

刪除元素

刪除元素對應方法 deleteHead

  • 如果 stack2 為空,則將 stack1 裡的所有元素彈出插入到 stack2
  • 如果 stack2 仍為空,則返回 -1,否則從 stack2 彈出一個元素並返回

程式碼

class CQueue {
    Deque<Integer> stack1;
    Deque<Integer> stack2;

    public CQueue() {
        stack1 = new LinkedList<Integer>();
        stack2 = new LinkedList<Integer>();
    }

    public void appendTail(int value) {
        stack1.push(value);
    }

    public int deleteHead() {
        // 如果第二個棧為空
        if (stack2.isEmpty()) {
            while (!stack1.isEmpty()) {
                stack2.push(stack1.pop());
            }
        } 
        if (stack2.isEmpty()) {
            return -1;
        } else {
            int deleteItem = stack2.pop();
            return deleteItem;
        }
    }
}

個人理解

  1. 個人測試,使用 Stack 也是可以執行成功的,但是 Stack 是 JDK 1.0 的產物,它繼承自 Vector,Vector 都不推薦使用了,所以 Stack 也不被推薦使用了。這點我是不知道的。
  2. Deque:Deque 是繼承自 Queue。Java 中的 Deque,即 “double ended queue” 的縮寫,是 Java 中的雙端佇列集合型別。Deque 具備普通佇列的 FIFO 的功能,同時它也具備了 Stack 的 LIFO 功能,並且保留了 push 和 pop 函式,所以使用起來應該是一點障礙都沒有。
  3. ArrayDeque: 是 Deque 介面的一種具體實現,是依賴於可變陣列來實現的。ArrayDeque 沒有容量限制,可根據需求自動進行擴容。ArrayDeque 可以作為棧來使用,效率要高於 Stack。ArrayDeque 也可以作為佇列來使用,效率相較於基於雙向連結串列的 LinkedList 也要更好一些。注意,ArrayDeque 不支援為 null 的元素。
  4. 注意宣告時要增加型別 Integert
  5. 測試發現使用 ArrayDeque 也可以。

複雜度分析

  • 時間複雜度:對於插入和刪除操作,時間複雜度均為 O(1)。插入不多說,對於刪除操作,雖然看起來是 O(N) 的時間複雜度,但是仔細考慮下每個元素只會「至多被插入和彈出 stack2 一次」,因此均攤下來每個元素被刪除的時間複雜度仍為 O(1)。
  • 空間複雜度O(N) :需要使用兩個棧儲存已有的元素。

來源:力扣(LeetCode)
連結:leetcode-cn.com/problems/yong-lian...

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章