Hi 你們好,我是張小豬。歡迎來到『寶寶也能看懂』系列特別篇 - 官方小活動 『30-Day LeetCoding Challenge』。git
這裏是 4 月 10 號的題,也是題目列表中的第 155 題 -- 『最小棧』github
設計一個支持 push
,pop
,top
操做,並能在常數時間內檢索到最小元素的棧。shell
push(x)
—— 將元素 x 推入棧中。pop()
—— 刪除棧頂的元素。top()
—— 獲取棧頂元素。getMin()
—— 檢索棧中的最小元素。示例:segmentfault
MinStack minStack = new MinStack(); minStack.push(-2); minStack.push(0); minStack.push(-3); minStack.getMin(); --> 返回 -3. minStack.pop(); minStack.top(); --> 返回 0. minStack.getMin(); --> 返回 -2.
EASY數組
題目要求很簡單,就是要封裝一個叫作 MinStack
的類,幾個操做都是普通的棧操做,不過多了一個返回最小的元素值。因爲原生 JS 的 Array
就集合了隊列和棧的操做行爲,因此咱們能夠直接基於它來實現。優化
直接基於原生的 Array
來實現棧的操做,另外咱們用一個變量來記錄棧內數據的最小值。這裏小豬用一個 _top
指針來標識棧頂的位置,從而避免數據的擦除開銷和數組動態縮短的開銷,另外在每一次 pop
的時候經過遍歷去更新記錄的最小值。具體代碼以下:this
class MinStack { constructor() { this._top = -1; this.data = []; this.min = Number.MAX_SAFE_INTEGER; } push(n) { this.data[++this._top] = n; n < this.min && (this.min = n); } pop() { this.min = Number.MAX_SAFE_INTEGER; for (let i = --this._top; i >= 0; --i) { this.data[i] < this.min && (this.min = this.data[i]); } } top() { return this.data[this._top]; } getMin() { return this.min; } }
上述代碼有個問題,pop
操做的時間複雜度實際上是 O(n),由於須要經過遍從來完成最小值的更新。咱們來嘗試把它變成 O(1)。spa
爲了直接更新最小值,那麼它可能來自於能夠直接計算或者提早算好了存起來。因爲數據並無什麼數學聯繫,因此直接計算顯然是不現實的,那麼咱們就從提早算好來考慮。咱們能夠想象一下在插入一個新數據的時候發生的狀況:當前棧中的最小值我是知道的;新數據是否最小我也是知道的。那麼就至關於插入數據前的最小值和插入數據後的最小值我都知道。那麼反過來,它們其實也就是彈出數據前和彈出數據後的最小值。設計
到此,咱們便獲得了實現思路。具體代碼以下:指針
class MinStack { constructor() { this._top = -1; this.data = []; this.min = Number.MAX_SAFE_INTEGER; } push(n) { this.data[++this._top] = this.min; this.data[++this._top] = n; n < this.min && (this.min = n); } pop() { this.min = this.data[--this._top]; --this._top; } top() { return this.data[this._top]; } getMin() { return this.min; } }
優化方式中包含了一點思惟的轉換,不過也很是簡單,但願能幫助到有須要的小夥伴。
若是以爲不錯的話,記得『三連』哦。小豬愛大家喲~