1. 程式人生 > 實用技巧 >劍指Offer_#59-II_佇列的最大值

劍指Offer_#59-II_佇列的最大值

劍指Offer_#59-II_佇列的最大值

Contents

題目

請定義一個佇列並實現函式 max_value 得到佇列裡的最大值,要求函式max_value、push_back 和 pop_front 的均攤時間複雜度都是O(1)。
若佇列為空,pop_front 和 max_value需要返回 -1
示例 1:

輸入: 
["MaxQueue","push_back","push_back","max_value","pop_front","max_value"]
[[],[1],[2],[],[],[]]
輸出:[null,null,null,2,1,2]

示例 2:

輸入: 
["MaxQueue","pop_front","max_value"]
[[],[],[]]
輸出:[null,-1,-1]

限制:
1 <= push_back,pop_front,max_value的總運算元<= 10000
1 <= value <= 10^5

思路分析

這一題跟劍指Offer_#59-I_滑動視窗的最大值劍指Offer_#30_包含min函式的棧都有共通之處,可以說是這兩題的一個結合。
#30題中,我們使用一個輔助棧來儲存每種狀態下的最小值。與30題不同的是,這裡是實現佇列結構,所以不能用棧作為輔助變數。可以借鑑#59題中的雙端佇列結構來實現功能,即雙端佇列作為輔助變數,儲存每種狀態下的最大值。在操作原始資料佇列的同時,同步操作輔助雙端佇列。使得無論什麼時候,雙端佇列的第一個元素就是原始資料佇列的最大值。
詳見如下圖解,來自

評論區題解

解答

class MaxQueue {
    Deque<Integer> maxDeque;
    Queue<Integer> queue;
    
    public MaxQueue() {
        queue = new LinkedList<>();
        maxDeque = new LinkedList<>();
    }
    
    public int max_value() {
        if(!maxDeque.isEmpty() && !queue.isEmpty())
            return
maxDeque.peekFirst(); else return -1; } public void push_back(int value) { queue.offer(value); while(!maxDeque.isEmpty() && value > maxDeque.peekLast()) maxDeque.removeLast(); maxDeque.addLast(value); } public int pop_front() { //ERROR:Integer作為包裝類物件,不能直接用==比較,必須用equals()方法比較,見《Core Java》P193 if(!maxDeque.isEmpty() && maxDeque.peekFirst().equals(queue.peek())) maxDeque.removeFirst(); if(!queue.isEmpty()) return queue.poll(); else return -1; } }

複雜度分析

時間複雜度:max_value、push_back 和 pop_front 的複雜度都是O(1)
空間複雜度:O(n),需要藉助一個輔助的雙端佇列