LeetCode #155 Min Stack - 刷題之旅
1 題目描述
這題的重點在於要實現一個可以取得最小值的 stack,並且要求時間複雜度為 O(1)。解題思路的重點是,你要怎麼確保在 push()
的時候,更新最小值,並且在 pop()
的時候,如果 pop()
出當前最小值時,也要更新最小值。
2 解法
2.1 我的解法
有沒有發現重點,當 pop()
和 push()
的時候,最小值也會有所更新,在 pop()
的時候,最小的值被剔除時,我們希望取得第二小,因此我們會需要一個 min_stack
來記錄當前最小值,如果遇到當前更小的,就 push()
進去 min_stack
裡面。這樣儘管最小的被 pop() 出去,我們仍然可以取得第二小的值。
大概是這種感覺:
每當 push 新的值進去時,都要與
min_stack[-1]
最小值比較是否更小,若更小,也要 push 進去min_stack
裡面。
每當 pop 出去時,也要檢查 pop 出去的值是否是當前的最小值,若是,也要把當前的
min_stack[-1]
pop 出去
其他的功能就跟 stack 一樣,在 python 可以使用 list 來實現 stack 的功能。 top() 可以使用 list[-1] 的方式取得,他仍然時間複雜度是 O(1)。下面註解的地方是我原本寫的,但是經過參考別人的後發現有更簡潔的寫法,所以我就改成更簡潔的寫法,註解可以參考。
1 | class MinStack: |
時間複雜度O(1) push(), pop(), top(), getMin() 操作的時間複雜度均為 O(1)。
空間複雜度O(n) 由於 min_stack 和 stack 存儲 n 個不同的數字,因此空間複雜度為 O(n)。
2.2 其他方法
還有一種方法,可以讓程式碼更簡潔,但是空間複雜度方便可能會比第一個方法更大,那就是在 push()
的時候,不管是不是最小值,都要 push 進去 min_stack
裡面,只是 push 進去的必須是當前的最小值,這樣在 pop()
的時候,就不用檢查是否是最小值,直接 pop 出去就好。這樣的好處是程式碼更簡潔,但是空間複雜度可能會比較大,因為 min_stack
裡面會有很多重複的值。
大概是這種感覺:
1 | class MinStack2: |
我們仔細看一下這兩個方法的差異:
1 | # 第一種方法 |
時間複雜度O(1) push()
, pop()
, top()
, getMin()
操作的時間複雜度均為 O(1)。
空間複雜度O(n) 由於 min_stack
和 stack
存儲 n 個不同的數字,因此空間複雜度為 O(n)。
3 總結
今天偷看了一下,一開始想不透到底要怎麼用 O(1) 的時間複雜度就可以做到 pop() 後仍然保持最小值,一開始都是用一個變數儲存最小值,但是沒想到這題的精髓在使用 stack 紀錄最小值,這樣在 pop() 的時候,也可以保持最小值。自己不應該每次看到 O(1) 就要無腦想用 Hash Table,這是無序的狀態下搜尋某個關鍵字使用,但是這題是有序的,所以使用 stack 來記錄最小值是一個很好的方法。