1. 程式人生 > >Leetcode 155:最小棧(超詳細的解法!!!)

Leetcode 155:最小棧(超詳細的解法!!!)

設計一個支援 push,pop,top 操作,並能在常數時間內檢索到最小元素的棧。

  • push(x) – 將元素 x 推入棧中。
  • pop() – 刪除棧頂的元素。
  • top() – 獲取棧頂元素。
  • getMin() – 檢索棧中的最小元素。

示例:

MinStack minStack = new MinStack();
minStack.push(-2);
minStack.push(0);
minStack.push(-3);
minStack.getMin();   --> 返回 -3.
minStack.pop();
minStack.top();      --> 返回 0.
minStack.getMin();   --> 返回 -2.

解題思路

由於問題中沒有講述對於錯誤輸入的操作,所以我們預設沒有錯誤輸入。最簡單的思路就是對陣列的操作

class MinStack(object):
    def __init__(self):
        """
        initialize your data structure here.
        """
        self.data = []       

    def push(self, x):
        """
        :type x: int
        :rtype: void
        """
        self.
data.append(x) def pop(self): """ :rtype: void """ self.data.pop() def top(self): """ :rtype: int """ return self.data[-1] def getMin(self): """ :rtype: int """ return min(self.data)

但是這個getMin

無法在常數時間內找到最小值,所以我們可以新增一個變數,記錄堆中的最小值。

    def push(self, x):
        """
        :type x: int
        :rtype: void
        """
        if x < self.min_val:
            self.min_val = x        
        self.data.append(x)

我們的pop操作也應該隨之改變,如果恰好彈出最小值呢?這要怎麼辦?一種策略就是再建一個棧,用於存放最小值。

class MinStack(object):
    def __init__(self):
        """
        initialize your data structure here.
        """
        self.s1 = [] 
        self.s2 = []

    def push(self, x):
        """
        :type x: int
        :rtype: void
        """
        if not self.s2 or x <= self.getMin():
            self.s2.append(x) 
            
        self.s1.append(x)

    def pop(self):
        """
        :rtype: void
        """
        if self.s1[-1] == self.getMin():
            self.s2.pop()
            
        self.s1.pop()

    def top(self):
        """
        :rtype: int
        """
        return self.s1[-1]

    def getMin(self):
        """
        :rtype: int
        """
        return self.s2[-1]

還有一種策略是在push的時候,我們也將min_val同時push進去,然後在pop的時候判斷min_valdata最後一個元素是不是相同,相同的話(恰好要彈出最小元素),我們就先pop出最小元素,然後更新此時的min_val(此時應該是data[-1]),然後再進行一次pop。例如

此時我們要考慮加入-3了,因為-3 < -2

我們首先將min_val,也就是-2壓入,然後再壓入-3。此時更新我們的min_val=-3

def push(self, x):
    """
    :type x: int
    :rtype: void
    """
    if x <= self.min_val:
        self.data.append(self.min_val)
        self.min_val = x

    self.data.append(x)

def pop(self):
    """
    :rtype: void
    """
    if self.data[-1] == self.min_val:
        self.data.pop()
        self.min_val = self.data[-1]
        self.data.pop()
    else:
        self.data.pop()

總的思路就是當訪問到的元素最小時,我們一定先要儲存上一次的最小元素,然後再更新最小元素。

reference:

https://leetcode.com/problems/min-stack/discuss/49016/C%2B%2B-using-two-stacks-quite-short-and-easy-to-understand

https://leetcode.com/problems/min-stack/discuss/49031/Share-my-Java-solution-with-ONLY-ONE-stack

我將該問題的其他語言版本新增到了我的GitHub Leetcode

如有問題,希望大家指出!!!