#155 Min Stack
frequently reported atBloombergOracleAmazonMicrosoftGoogleMeta
the problem
In plain words
Design a stack with push(val), pop(), top() and getMin(). getMin() returns the smallest element currently in the stack. Every operation must run in O(1) time.
in push(-2), push(0), push(-3), getMin(), pop(), top(), getMin()
out -3, 0, -2
After popping -3 the minimum goes back to -2.
- −2³¹ ≤ val ≤ 2³¹ − 1
- pop, top and getMin are only called on a non-empty stack
- At most 3·10⁴ calls
your turn
Try it before you peek
Read the examples, say the brute force out loud, then write code: here or on LeetCode ↗. Stuck for 20 minutes? Open one hint at a time.
Solve it in the browser
Design: implement every operation. Compiled by the real javac (Java 17) and judged right here — nothing is sent anywhere.
Solutions are hidden so you can try first. Even 20 minutes of real effort makes the answer stick far better than reading it.
Marking the problem solved, or opening every hint, also shows it.
the aha
Key insight
patternStack & queue design
The minimum only changes when you push or pop — and a stack only changes at the top. So remember, for each level of the stack, what the minimum was at that moment.
solutions
From brute force to optimal
A plain stack; getMin walks every element.
- push/pop/top use the stack directly.
- getMin loops over all items and keeps the smallest.
getMin visits every element; fails the O(1) requirement.
The stack itself.
class ScanMinStack { private final Deque<Integer> stack = new ArrayDeque<>(); public void push(int val) { stack.push(val); } public void pop() { stack.pop(); } public int top() { return stack.peek(); } public int getMin() { // walks every element: O(n) int min = Integer.MAX_VALUE; for (int x : stack) min = Math.min(min, x); return min; }}Each entry also stores the minimum of itself and everything below it. The top entry always knows the current minimum.
- push(val): min = empty ? val : min(val, top.min); push {val, min}.
- pop(): pop the pair — the entry below already holds the older minimum.
- top() = top.value, getMin() = top.min.
Each call touches only the top entry.
Two ints per entry.
class MinStack { // each entry = {value, minimum of this entry and everything below it} private final Deque<int[]> stack = new ArrayDeque<>(); public void push(int val) { int min = stack.isEmpty() ? val : Math.min(val, stack.peek()[1]); stack.push(new int[] {val, min}); } public void pop() { stack.pop(); } // the entry below already knows its own min public int top() { return stack.peek()[0]; } public int getMin() { return stack.peek()[1]; }}Dry run
A second stack only records new minimums (including ties), so it is often much shorter.
- push(val): push to stack; if mins is empty or val ≤ mins.top, push val to mins too.
- pop(): pop from stack; if that value equals mins.top, pop mins too.
- getMin() = mins.top.
Each call does at most one push/pop on each stack.
Worst case (decreasing pushes) both stacks hold n items; usually mins is smaller.
class TwoStackMinStack { private final Deque<Integer> stack = new ArrayDeque<>(); private final Deque<Integer> mins = new ArrayDeque<>(); // top = current minimum public void push(int val) { stack.push(val); if (mins.isEmpty() || val <= mins.peek()) mins.push(val); // <= keeps duplicates of the min } public void pop() { int removed = stack.pop(); // unbox to int so == below compares values, not references if (removed == mins.peek()) mins.pop(); } public int top() { return stack.peek(); } public int getMin() { return mins.peek(); }}in the room
How to say it in the interview
talk track
- Point out that a single
minvariable fails: after popping the minimum, you can't recover the previous one. - Present the pair idea: "each level remembers the min at that level."
- Explain why the two-stack version uses
<=: duplicates of the minimum must each be recorded, or popping one would lose the other.
traps
- Using
<instead of<=when pushing to the min stack — push −2, −2, pop → getMin breaks. - Comparing
stack.peek() == mins.peek()as twoIntegerobjects: works for small numbers (cache), fails for 1000. Unbox tointfirst.
what they ask next
Follow-ups
Can you do it with O(1) extra space (no second stack)?
Yes: store differences (val − min) as long and update min when a negative difference is pushed/popped. Clever, but easy to get wrong — mention it, code the pair version.
Max Stack (LC 716) with popMax()?
popMax needs to remove from the middle: use a TreeMap<value, list of nodes> plus a doubly linked list for O(log n) per operation.
before you submit
Edge cases to test
- Duplicate minimums: push 1, push 1, pop → getMin() must still be 1 (that's why the two-stack version uses <=).
- Values outside −128..127, like 1000: comparing two
Integers with == compares references and breaks. - Integer.MIN_VALUE and Integer.MAX_VALUE are valid values; a min-so-far that starts at MAX_VALUE must still work.
practise next
Similar problems
- #232Implement Queue using StacksEasyin Queues
- #622Design Circular QueueMediumin Queues
- #146LRU CacheMediumin Linked Lists