By Fatskills Exam Guides Team — the exam nerds behind 28,500+ quizzes and 2.1M practice questions across 500+ global exams.
"This problem appears in 1 out of every 3 onsite interviews—nail it, and you prove you can design O(1) operations while handling edge cases like a senior engineer."
Before tackling Min Stack, ensure you understand: 1. Stacks (LIFO) – Push, pop, peek operations in O(1) time. 2. Time/Space Trade-offs – How auxiliary data structures (e.g., extra stacks) impact complexity. 3. Amortized Analysis – Why some operations are O(1) on average (e.g., dynamic arrays).
(value, min)
(x, min(x, current_min))
x
Follow these exact steps for every Min Stack problem:
getMin()
Ask if duplicates are allowed (they usually are).
Choose a Data Structure
main_stack
min_stack
Option 2: Single stack storing (value, current_min) tuples.
(value, current_min)
Initialize
infinity
None
If using tuples, initialize with (value, value) for the first push.
(value, value)
Push Operation
x <= min_stack[-1]
Tuples: Push (x, min(x, current_min)).
Pop Operation
min_stack[-1]
Tuples: Pop the tuple; the min is automatically updated.
Top Operation
Return main_stack[-1] (or the first element of the tuple).
main_stack[-1]
GetMin Operation
Return min_stack[-1] (or the second element of the tuple).
Edge Cases
Duplicate mins (ensure min_stack doesn’t pop prematurely).
Time/Space Complexity
Space: O(n) (worst case, all elements are decreasing).
Optimize (If Asked)
Problem: Design a stack that supports push, pop, top, and getMin in O(1) time.
push
pop
top
getMin
class MinStack: def __init__(self): self.main_stack = [] self.min_stack = [] def push(self, x: int) -> None: self.main_stack.append(x) if not self.min_stack or x <= self.min_stack[-1]: self.min_stack.append(x) def pop(self) -> None: if not self.main_stack: return popped = self.main_stack.pop() if popped == self.min_stack[-1]: self.min_stack.pop() def top(self) -> int: return self.main_stack[-1] def getMin(self) -> int: return self.min_stack[-1]
x <= current_min
Problem: Optimize space by using one stack while maintaining O(1) operations.
current_min = min(x, stack[-1][1])
stack[-1][1]
class MinStack: def __init__(self): self.stack = [] def push(self, x: int) -> None: if not self.stack: self.stack.append((x, x)) else: current_min = min(x, self.stack[-1][1]) self.stack.append((x, current_min)) def pop(self) -> None: if self.stack: self.stack.pop() def top(self) -> int: return self.stack[-1][0] def getMin(self) -> int: return self.stack[-1][1]
Problem: Can you design a Min Stack with O(1) space?
class MinStack: def __init__(self): self.stack = [] def push(self, x: int) -> None: self.stack.append(x) def pop(self) -> None: if self.stack: self.stack.pop() def top(self) -> int: return self.stack[-1] def getMin(self) -> int: return min(self.stack) # O(n) time!
if not stack
pop()
top()
x < current_min
popped_value == min_stack[-1]
<=
<
>=
"Alright, let’s lock this in. For Min Stack, you’ve got two go-to approaches: 1. Two stacks – main_stack for values, min_stack for mins. Push to min_stack only when x <= current_min. Pop from min_stack only if the popped value equals the current min. 2. Single stack with tuples – Store (value, current_min) in one stack. Saves a little space but same complexity.
Edge cases? Empty stack, duplicates, all decreasing elements. Time complexity? O(1) for all operations. Space? O(n) worst case. And if they ask for O(1) space? Politely explain why it’s impossible—you need O(n) auxiliary space to track mins in O(1) time.
Now go crush that interview. You’ve got this." ?
Join 4M+ learners. Unlock unlimited quizzes, wrong-answer tracking, flashcards + reminders, study guides, and 1-on-1 challenges.