【LeetCode刷题-简单】155. 最小栈(python c++)

题目

设计一个支持 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.

 

1. 双栈

思路

我们使用两个栈:

  • 一个栈存放全部的元素,push,pop都是正常操作这个正常栈。
  • 另一个存放最小栈。 每次push,如果比最小栈的栈顶还小,我们就push进最小栈,否则不操作
  • 每次pop的时候,我们都判断其是否和最小栈栈顶元素相同,如果相同,那么我们pop掉最小栈的栈顶元素即可

关键点

  • 往minstack中 push的判断条件。 应该是stack为空或者x小于等于minstack栈顶元素

复杂度分析

  • 时间复杂度:O(1)
  • 空间复杂度:O(N)

Python

class MinStack:

    def __init__(self):
        """
        initialize your data structure here.
        """
        self.num_stk = []
        self.min_stk = []

    def push(self, x: int) -> None:
        if(len(self.num_stk) == 0 or x <= self.min_stk[-1]):
            self.min_stk.append(x)
        self.num_stk.append(x)

    def pop(self) -> None:
        last = self.num_stk.pop(-1)
        if(last == self.min_stk[-1]):
            self.min_stk.pop(-1)

    def top(self) -> int:
        return self.num_stk[-1]

    def getMin(self) -> int:
        return self.min_stk[-1]



# Your MinStack object will be instantiated and called as such:
# obj = MinStack()
# obj.push(x)
# obj.pop()
# param_3 = obj.top()
# param_4 = obj.getMin()

【LeetCode刷题-简单】155. 最小栈(python c++)_第1张图片

 

C++

class MinStack {
    list stk;
    list min;
public:
    /** initialize your data structure here. */
    MinStack() {
    }
    
    void push(int x) {
        if(min.empty() || min.front() >= x)
            min.push_front(x);
        stk.push_front(x);
    }
    
    void pop() {
        if(stk.front() == min.front())
            min.pop_front();
        stk.pop_front();
    }
    
    int top() {
        return stk.front();
    }
    
    int getMin() {
        return min.front();
    }
};

/**
 * Your MinStack object will be instantiated and called as such:
 * MinStack* obj = new MinStack();
 * obj->push(x);
 * obj->pop();
 * int param_3 = obj->top();
 * int param_4 = obj->getMin();
 */

【LeetCode刷题-简单】155. 最小栈(python c++)_第2张图片

 

2. 单栈

差值法

思路

符合直觉的方法是,每次对栈进行修改操作(push和pop)的时候更新最小值。 然后getMin只需要返回我们计算的最小值即可, top也是直接返回栈顶元素即可。 这种做法每次修改栈都需要更新最小值,因此时间复杂度是O(n).

 

是否有更高效的算法呢?答案是有的。

我们每次入栈的时候,保存的不再是真正的数字,而是它与当前最小值的差(当前元素没有入栈的时候的最小值)。 这样我们pop和top的时候拿到栈顶元素再加上上一个最小值即可。 另外我们在push和pop的时候去更新min,这样getMin的时候就简单了,直接返回min。

注意上面加粗的“上一个”,不是“当前的最小值”

经过上面的分析,问题的关键转化为“如何求得上一个最小值”,解决这个的关键点在于利用min。

pop或者top的时候:

  • 如果栈顶元素小于0,说明栈顶是当前最小的元素,它出栈会对min造成影响,我们需要去更新min。 上一个最小的是“min - 栈顶元素”,我们需要将上一个最小值更新为当前的最小值

因为栈顶元素入栈的时候的通过 栈顶元素 = 真实值 - 上一个最小的元素 得到的, 而真实值 = min, 因此可以得出上一个最小的元素 = 真实值 -栈顶元素

  • 如果栈顶元素大于0,说明它对最小值没有影响,上一个最小值就是上上个最小值。

关键点

  • 最小栈存储的不应该是真实值,而是真实值和min的差值
  • top的时候涉及到对数据的还原,这里千万注意是上一个最小值

复杂度分析

  • 时间复杂度:O(1)
  • 空间复杂度:O(1)
class MinStack:

    def __init__(self):
        """
        initialize your data structure here.
        """
        self.minV = float('inf')
        self.stack = []

    def push(self, x: int) -> None:
        self.stack.append(x - self.minV)
        if x < self.minV:
            self.minV = x

    def pop(self) -> None:
        if not self.stack:
            return
        tmp = self.stack.pop()
        if tmp < 0:
            self.minV -= tmp

    def top(self) -> int:
        if not self.stack:
            return
        tmp = self.stack[-1]
        if tmp < 0:
            return self.minV
        else:
            return self.minV + tmp

    def getMin(self) -> int:
        return self.minV

【LeetCode刷题-简单】155. 最小栈(python c++)_第3张图片

 

C++

 

 

 

 

 

 

 

 

你可能感兴趣的:(LeetCode刷题)