Logo for ammarahmed.ca
Medium
May 27, 2025
#stack
#class

155. Min Stack

Problem

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:

            1Input 2["MinStack","push","push","push","getMin","pop","top","getMin"] 3[[],[-2],[0],[-3],[],[],[],[]] 4 5Output 6[null,null,null,null,-3,null,0,-2] 7 8Explanation 9MinStack minStack = new MinStack(); 10minStack.push(-2); 11minStack.push(0); 12minStack.push(-3); 13minStack.getMin(); // return -3 14minStack.pop(); 15minStack.top(); // return 0 16minStack.getMin(); // return -2 17

            Constraints:

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

                  Approach

                  As expected, we'll use a stack to solve this problem, however, the complexity arises with implementing the minimum value logic in constant time.

                  To solve this issue, we can use two stacks within the MinStack. One will be our main stack that will track all of the values and the other will be our minStack that will track the minimum values.

                  To start, we initialize both of them.

                  For the push, we always push to the main stack. We only push to minStack if the minStack is empty (first minimum value) or if the value is less than or equal to the top of minStack. This way the minStack will always have the smallest value at the top.

                  For the pop, we always pop off the main stack. We only pop off the minStack when the top of the main stack is equal to the top of the minStack.

                  After this, the remaining methods are trivial.

                  For my specific solution, I implemented a generic, Stack[R any] struct to make using array-based stacks a little bit easier syntactically. I could have also used a linked-list based stack for better efficiency but this is sufficient.

                  Complexity

                  Time: O(1)

                  None of the methods do any iteration at all so it's all constant time.

                  Space: O(n)

                  We create two stacks that could potentially be the size of the inputs.

                  Solution

                  1type Stack[R any] struct { 2 stack []R 3} 4 5func (this *Stack[R]) Append(val R) { 6 this.stack = append(this.stack, val) 7} 8 9func (this *Stack[R]) Len() int { 10 return len(this.stack) 11} 12 13func (this *Stack[R]) Pop() *R { 14 if this.Len() == 0 { 15 return nil 16 } 17 val := this.stack[this.Len() - 1] 18 this.stack = this.stack[:this.Len() - 1] 19 return &val 20} 21 22func (this *Stack[R]) Peek() *R { 23 if this.Len() == 0 { 24 return nil 25 } 26 return &this.stack[this.Len() - 1] 27} 28 29type MinStack struct { 30 stack Stack[int] 31 minStack Stack[int] 32} 33 34func Constructor() MinStack { 35 return MinStack{ 36 stack: Stack[int]{}, 37 minStack: Stack[int]{}, 38 } 39} 40 41func (this *MinStack) Push(val int) { 42 if this.minStack.Len() == 0 || val <= *this.minStack.Peek() { 43 this.minStack.Append(val) 44 } 45 this.stack.Append(val) 46} 47 48func (this *MinStack) Pop() { 49 if this.Top() == *this.minStack.Peek() { 50 this.minStack.Pop() 51 } 52 this.stack.Pop() 53} 54 55func (this *MinStack) Top() int { 56 return *this.stack.Peek() 57} 58 59func (this *MinStack) GetMin() int { 60 return *this.minStack.Peek() 61} 62