Calls pointer walks the calls · return value underneath
stackvalues
minStackmin at or below each height
class MinStack { // min at or below each level private Deque<Integer> stack; private Deque<Integer> minStack; public MinStack() { stack = new ArrayDeque<>(); minStack = new ArrayDeque<>(); } public void push(int val) { stack.push(val); if (!minStack.isEmpty()) { val = Math.min(val, minStack.peek()); } minStack.push(val); } public void pop() { stack.pop(); minStack.pop(); } public int top() { return stack.peek(); } public int getMin() { return minStack.peek(); }}
- call
- —
- val
- —
- stack
- []
- minStack
- []
- output
- []
Why it works
- Brute force scans:
getMinrunsCollections.min(stack), O(n) per call. Keeping one "current min" variable is not enough either: once that value is popped, finding the next min means a rescan. - Key invariant:
minStackat height h is the minimum of the h lowest values ofstack. A stack only changes at the top, so everything below height h stays put, and so does its minimum. Store it once per height. - Every call is O(1).
pushneeds onlyvaland the level below;popdrops both tops and the level below is already right;getMinreads one cell. Space is O(n), one min per value. - Pitfall: duplicate minimums. The space-saving variant only pushes to
minStackwhenval <= minStack.peek(). Write<instead and push 0, 1, 0 then pop loses the remaining 0. The per-height version here stores every level, so ties are safe. In that variant compare the popped value with.equals, not==: boxedIntegers outside −128..127 are different objects. - Same idea, one stack: push pairs
{val, minSoFar}(anint[]). Or keep a single min and storeval − min, decoding on pop, for O(1) extra space. - Follow-up: Max Stack (716) needs
popMaxtoo, so it moves to aTreeMapor two heaps. A min or max over a sliding window uses a monotonicArrayDeque(239).