Min Stack
Min Stack#
Problem#
Design a stack that supports the usual push, pop, and top operations
plus a get_min operation that returns the smallest element currently in the
stack. Every operation should run in constant time.
Example#
Push 3, push 5, get_min returns 3. Push 2, get_min returns 2. Pop, and
get_min returns 3 again. Push 1, get_min returns 1.
Brute force#
Keep a single stack and scan it on every get_min call. That makes get_min
O(n), which fails the constant-time requirement.
Optimal approach#
Store the running minimum next to each value. Each stack entry is a pair: the
value pushed and the smallest value seen up to and including that push. When
you push, the new minimum is min(new_value, current_min). When you pop, the
previous minimum is automatically restored because it lives in the entry now
on top. get_min just reads the second field of the top entry, all in O(1).
Solution#
1class MinStack:
2 def __init__(self):
3 self._stack = [] # list of (value, min_so_far)
4
5 def push(self, value: int) -> None:
6 current_min = value
7 if self._stack:
8 current_min = min(value, self._stack[-1][1])
9 self._stack.append((value, current_min))
10
11 def pop(self) -> None:
12 self._stack.pop()
13
14 def top(self) -> int:
15 return self._stack[-1][0]
16
17 def get_min(self) -> int:
18 return self._stack[-1][1]
19
20
21stack = MinStack()
22stack.push(3)
23stack.push(5)
24print(stack.get_min()) # 3
25stack.push(2)
26print(stack.get_min()) # 2
27stack.pop()
28print(stack.get_min()) # 3
Complexity#
- Time: O(1) for every operation.
- Space: O(n) to hold n paired entries.
Review the stacks and queues topic for more stack design questions, then continue the 60-day challenge.