[LeetCode] 面試題59 - II. 佇列的最大值
阿新 • • 發佈:2020-03-07
題目:
分析:
本題要求三個方法的時間複雜度都是O(1),對於push_back和pop_front都是好實現的
但是對於max_value,正常情況下要進行遍歷才能獲得最大值,那麼如何才能在O(1)的時間複雜度下獲得最大值?
O(1)時間複雜度意味著直接便可以獲得最大值,一開始的想法是設定兩個變數,一個最大值max,一個第二大值max_2,每次push_back時進行更新,若pop_front的值與最大值相同,便讓max = max_2
但這樣有個問題,當連續兩次pop_front,同時前兩大的數字都被pop出去時,max與max_2儲存的值都是錯誤的,如果要重新確定max與max_2的值,又要進行遍歷了
後來看了題解,裡面提到維護一個排序佇列(雙向),當一個元素cur插入時,它前面所有比它小的值都不會對最大值有影響,而比它大的已經出隊了,因為正常出隊時,出到cur時,它前面的所有值已全部出隊,所以插入時更新雙向排序佇列,只保留比當前值大的值的有序佇列,便可以直接取到max_value,同時不必擔心連續出隊導致的找不大最大值,如果出隊的值真好是當前的最大值,只需要將雙向佇列的隊頭出隊即可
至於為何時間複雜度為O(1), 題解中提到:
我的理解是,在插入時,會將小於當前值的值出隊,不過這個出隊的操作次數是有限的,一個插入操作最多隻有n個出隊操作,更多的情況是小於n個操作,也就是說n個插入操作總共進行了n次出隊,平均下來就是O(1)的複雜度
程式碼:
class MaxQueue { queue<int> que; deque<int> deq; public: MaxQueue() { } int max_value() { if(deq.empty()) return -1; return deq.front(); } void push_back(int value) { while(!deq.empty() && deq.back()<value) deq.pop_back(); deq.push_back(value); que.push(value); } int pop_front() { if(que.empty()) return -1; int res = que.front(); que.pop(); if(res == deq.front()) deq.pop_front(); return res; } }; /** * Your MaxQueue object will be instantiated and called as such: * MaxQueue* obj = new MaxQueue(); * int param_1 = obj->max_value(); * obj->push_back(value); * int param_3 = obj->pop_front(); */
&n