Post

LC 155 - Min Stack

LC 155 - Min Stack

Question

Design a stack that supports push, pop, top, and retrieving the minimum element in constant time.

Implement the MinStack class:

  • MinStack() initializes the stack object.
  • void push(int val) pushes the element val onto the stack.
  • void pop() removes the element on the top of the stack.
  • int top() gets the top element of the stack.
  • int getMin() retrieves the minimum element in the stack.

You must implement a solution with O(1) time complexity for each function.

Example 1:

1
2
3
4
5
6
Input
["MinStack","push","push","push","getMin","pop","top","getMin"]
[[],[-2],[0],[-3],[],[],[],[]]

Output
[null,null,null,null,-3,null,0,-2]

Explanation MinStack minStack = new MinStack();
minStack.push(-2);
minStack.push(0);
minStack.push(-3);
minStack.getMin(); // return -3
minStack.pop();
minStack.top(); // return 0
minStack.getMin(); // return -2

Constraints:

  • -231 <= val <= 231 - 1
  • Methods poptop and getMin operations will always be called on non-empty stacks.
  • At most 3 * 104 calls will be made to pushpoptop, and getMin.

Question here and solution here

Solution

concept

The main issue here is the getMin() method which needs to be $O(1)$. Normal stack do not have this feature. In this case we use 2 stack to keep track: 1 for the normal store and retrieval, and 1 for storing the current minimum value. When we add in a value, we will add in to the first stack normally, the second stack will also be added but comparing to the -1 index of the min_stack (i.e. current minimum value). When we pop value, we pop from both stack.

Take note that my implementation initially keep track minimum in self.min and only update this value in the push method but not during pop method and this is wrong. It is much easier just to look at -1 index of the min_stack to know what is the current minimum in the stack since this property propagate through the min_stack.

code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class MinStack:

    def __init__(self):
        self.stack = []
        self.min_stack = []

    def push(self, val: int) -> None:
        self.stack.append(val)
        if self.min_stack:
            self.min_stack.append(min(val, self.min_stack[-1]))
        else:
            self.min_stack.append(val)
        
    def pop(self) -> None:
        self.stack.pop()
        self.min_stack.pop()
        
    def top(self) -> int:
        return self.stack[-1]
        
    def getMin(self) -> int:
        return self.min_stack[-1]

Complexity

time: $O(1)$
space: $O(n)$

This post is licensed under CC BY 4.0 by the author.