> [!META]- Inline Metadata > [tags:: #career #concepts/programming/stacks #leetcode/stacks ] > [project group:: Neetcode 150] > [difficulty:: medium] > [status:: done] > [link:: https://leetcode.com/problems/min-stack/] > [up:: [[Leetcode MOC]]] ## Problem Design a stack that supports push, pop, top, and retrieving the minimum element in constant time. Implement the `MinStack` class: - `MinStack()` initializes the stack object. - `void push(int val)` pushes the element `val` onto the stack. - `void pop()` removes the element on the top of the stack. - `int top()` gets the top element of the stack. - `int getMin()` retrieves the minimum element in the stack. You must implement a solution with `O(1)` time complexity for each function. ### Example 1 ``` Input ["MinStack","push","push","push","getMin","pop","top","getMin"] [[],[-2],[0],[-3],[],[],[],[]] Output [null,null,null,null,-3,null,0,-2] Explanation MinStack minStack = new MinStack(); minStack.push(-2); minStack.push(0); minStack.push(-3); minStack.getMin(); // return -3 minStack.pop(); minStack.top(); // return 0 minStack.getMin(); // return -2 ``` ### Constraints - `-2^31 <= val <= 2^31 - 1` - Methods `pop`, `top` and `getMin` operations will always be called on **non-empty** stacks. - At most `3 * 10^4` calls will be made to `push`, `pop`, `top`, and `getMin`. ## Solution ### Mine #### Python This maintains a second list of tuples that works in constant time for insertion and returning min, but not for popping. A min heap seems like overkill here? ```python class MinStack: def __init__(self): self.stack = [] self.min = [] # list of index, val pairs def push(self, val: int) -> None: self.stack.append(val) if self.min: if val == self.min[0][1]: self.min.append((len(self.stack), val)) elif val < self.min[0][1]: self.min = [(len(self.stack), val)] else: self.min = [(len(self.stack), val)] def pop(self) -> None: popped_index = len(self.stack) popped_val = self.stack.pop() if self.min and popped_val == self.min[-1][1]: self.min.pop() def top(self) -> int: return self.stack[-1] def getMin(self) -> int: return self.min[0][1] ``` So instead we maintain a second list as a stack, but each index holds whatever the minimum is for the state of the stack when the value was added to that point. ```python class MinStack: def __init__(self): self.stack = [] self.min = [] # list of mins at each point def push(self, val: int) -> None: self.stack.append(val) if not self.min or val < self.min[-1]: self.min.append(val) else: self.min.append(self.min[-1]) def pop(self) -> None: self.min.pop() self.stack.pop() def top(self) -> int: return self.stack[-1] def getMin(self) -> int: return self.min[-1] ``` #### Rust ### LC's ## Things I Learned The Neetcode hint makes sense - keep a record of the minimum value at each level of the stack. ## Scratchpad