Min Stack
Stack with O(1) push, pop, top, and getMin — pair each value with the min so far, or dual stacks.
- dsa
- stack
- interview
- Meta
The problem
Design a stack that supports push, pop, top, and retrieving the minimum element in constant time.
MinStack minStack = new MinStack();
minStack.push(-2);
minStack.push(0);
minStack.push(-3);
minStack.getMin(); // -3
minStack.pop();
minStack.top(); // 0
minStack.getMin(); // -2
Brute force
On getMin, scan the stack. O(n) min — rejected by the problem statement.
Optimal: store min alongside each value
Each entry is { val, min } where min is the minimum of the stack including this val.
class MinStack {
private stack: { val: number; min: number }[] = [];
push(val: number): void {
const min = this.stack.length
? Math.min(val, this.stack[this.stack.length - 1].min)
: val;
this.stack.push({ val, min });
}
pop(): void {
this.stack.pop();
}
top(): number {
return this.stack[this.stack.length - 1].val;
}
getMin(): number {
return this.stack[this.stack.length - 1].min;
}
}
Dual-stack variant
Main stack of values + min stack that pushes when val <= currentMin (use <= so duplicates of the min pop correctly).
class MinStackDual {
private vals: number[] = [];
private mins: number[] = [];
push(val: number): void {
this.vals.push(val);
if (!this.mins.length || val <= this.mins[this.mins.length - 1]) {
this.mins.push(val);
}
}
pop(): void {
const v = this.vals.pop();
if (v === this.mins[this.mins.length - 1]) this.mins.pop();
}
top(): number {
return this.vals[this.vals.length - 1];
}
getMin(): number {
return this.mins[this.mins.length - 1];
}
}
| Time | O(1) all ops |
| Space | O(n) |
Edge cases
- Single element
- Many equal mins: push
-1,-1; pop one; min still-1— need<=on dual stack - Decreasing then increasing sequences
- Constraints usually guarantee ops on non-empty stack
Common bugs
- Dual stack only pushes on strict
<→ duplicate mins break on pop - Computing min only at push time without storing history
- Off-by-one on empty after pop
Interview delivery
- O(1) min means precompute on push.
- Pair method or dual stack.
- Stress-test equal minimums.
- State O(1)/O(n).
Related
Trace dual-stack
push -2 → vals[-2], mins[-2]
push 0 → vals[-2,0], mins[-2] (0 > min)
push -3 → vals[-2,0,-3], mins[-2,-3]
getMin → -3
pop → pop -3, also pop min
getMin → -2
Why <= not < on dual stack
push -1, push -1. If you only push min on strict <, mins has one -1. First pop removes a -1 but mins still shows -1 (ok accidentally)… until you pop again: vals empty of -1 but mins still has -1 → wrong. Use <= so each equal min is stacked.
Pair encoding alternative
Some solutions push 2*val - min encodings to save space — clever, error-prone in interviews. Prefer explicit pairs or dual stacks.
API contract
Clarify whether pop returns the value (LC void) and whether empty ops are possible. Don’t crash on empty if constraints guarantee safety — still write defensive optional checks if time allows.