AlgoMaster Logo

Min Stack

mediumFrequency6 min readUpdated June 23, 2026

Understanding the Problem

We need a stack that supports the usual push, pop, and top operations and also returns the minimum element at any time, with every operation running in O(1). The standard stack operations are easy. The hard part is getMin.

With a plain stack, finding the minimum means scanning every element, which is O(n). The question is how to track the minimum as elements come and go, without ever scanning.

The minimum can only change in two situations: when we push an element smaller than the current minimum, or when we pop an element that was the current minimum. So we need a way to recover what the minimum was before the popped element arrived.

Key Constraints:

  • -2^31 <= val <= 2^31 - 1 → Values span the full 32-bit signed integer range, including the minimum value -2147483648. A sentinel value chosen to mean "empty" could collide with a real input, so avoid that design.
  • At most 3 * 10^4 calls → The problem requires O(1) per operation regardless of call volume, so we need a design that tracks the minimum incrementally rather than recomputing it.
  • Operations on non-empty stacks → pop, top, and getMin are never called on an empty stack, so we do not need to handle that case.

Approach 1: Brute Force (Linear Scan for Min)

Intuition

Use a regular stack for push, pop, and top, then scan the entire stack whenever getMin is called. This ignores the O(1) requirement for getMin, but it establishes a correct baseline.

Push, pop, and top are already O(1) with a standard stack. Only getMin is expensive: each call iterates through all elements currently in the stack to find the smallest one.

Algorithm

  1. Maintain a standard stack (or list) to store elements.
  2. For push, add the element to the top of the stack.
  3. For pop, remove the top element.
  4. For top, return the top element without removing it.
  5. For getMin, iterate through all elements in the stack and return the smallest one.

Example Walkthrough

1push(-2): stack=[-2]
-2
Top
1/6

Code

The brute force is correct but getMin scans the entire stack on every call. The next approach tracks the minimum as elements are pushed and popped, so getMin never scans.

Approach 2: Two Stacks

Intuition

The minimum of a stack depends only on the elements currently in it, and because we only add and remove from the top, those elements are always a prefix of the push history. If we record what the minimum was at each level of the stack, popping an element restores the previous minimum.

One way to do this is with a second stack, the min stack. Every time we push a value, we also push the current minimum onto the min stack. When we pop, we pop from both. The top of the min stack always holds the current minimum.

Algorithm

  1. Initialize two stacks: one for values (stack) and one for tracking minimums (minStack).
  2. For push(val): push val onto stack. If minStack is empty or val is less than or equal to the current minimum, push val onto minStack. Otherwise, push the current minimum again (so minStack stays in sync).
  3. For pop(): pop from both stack and minStack.
  4. For top(): return the top of stack.
  5. For getMin(): return the top of minStack.

Example Walkthrough

stack
1push(5): stack=[5], min is 5
5
Top
minStack
1push min(5, -) = 5
5
Top
1/9

Code

The two-stack approach gives O(1) for every operation but maintains two separate data structures kept in sync. The next approach folds them into a single stack that stores pairs.

Approach 3: Single Stack with Pairs

Intuition

Instead of maintaining two separate stacks, store pairs of (value, currentMin) in a single stack. Each entry carries its own minimum snapshot. This produces the same answers as the two-stack approach with one data structure, which removes the need to keep two stacks in sync.

Algorithm

  1. Initialize a single stack that stores pairs (value, currentMinimum).
  2. For push(val): compute the new minimum as the smaller of val and the current stack's minimum (or val if the stack is empty). Push the pair (val, newMin).
  3. For pop(): pop the top pair.
  4. For top(): return the first element of the top pair.
  5. For getMin(): return the second element of the top pair.

Example Walkthrough

1push(-2): first element, min is -2 → push (-2, -2)
(-2, -2)
Top
1/7

Code