Welcome to Subscribe On Youtube

155. Min Stack

Description

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:

  • -231 <= val <= 231 - 1
  • Methods pop, top and getMin operations will always be called on non-empty stacks.
  • At most 3 * 104 calls will be made to push, pop, top, and getMin.

Solutions

To implement a Min Stack (LeetCode problem 155), which supports push, pop, top, and retrieving the minimum element in constant time, you can maintain two stacks: one to store all the elements (the main stack) and another to store the minimum elements (the min stack). The min stack helps in keeping track of the minimum elements at any given point, aligning with the operations performed on the main stack.

Explanation:

  • Initialization: Two empty lists are initialized; self.stack serves as the main stack, and self.min_stack keeps track of the minimum values.
  • Push: When a new value is pushed onto the stack, it is always added to self.stack. It is also added to self.min_stack if self.min_stack is empty or if the new value is less than or equal to the current minimum (the last element of self.min_stack).
  • Pop: When popping a value from the stack, if the value being popped is the current minimum (i.e., it matches the last element in self.min_stack), it is also popped from self.min_stack.
  • Top: The last element of self.stack is returned as the top element of the stack.
  • GetMin: The last element of self.min_stack, which is the current minimum, is returned.

This implementation ensures that all operations—push, pop, top, and getMin — run in constant time, satisfying the problem’s constraints.

  • class MinStack {
        private Deque<Integer> stk1 = new ArrayDeque<>();
        private Deque<Integer> stk2 = new ArrayDeque<>();
    
        public MinStack() {
            stk2.push(Integer.MAX_VALUE);
        }
    
        public void push(int val) {
            stk1.push(val);
            stk2.push(Math.min(val, stk2.peek()));
        }
    
        public void pop() {
            stk1.pop();
            stk2.pop();
        }
    
        public int top() {
            return stk1.peek();
        }
    
        public int getMin() {
            return stk2.peek();
        }
    }
    
    /**
     * Your MinStack object will be instantiated and called as such:
     * MinStack obj = new MinStack();
     * obj.push(val);
     * obj.pop();
     * int param_3 = obj.top();
     * int param_4 = obj.getMin();
     */
    
  • class MinStack {
    public:
        MinStack() {
            stk2.push(INT_MAX);
        }
    
        void push(int val) {
            stk1.push(val);
            stk2.push(min(val, stk2.top()));
        }
    
        void pop() {
            stk1.pop();
            stk2.pop();
        }
    
        int top() {
            return stk1.top();
        }
    
        int getMin() {
            return stk2.top();
        }
    
    private:
        stack<int> stk1;
        stack<int> stk2;
    };
    
    /**
     * Your MinStack object will be instantiated and called as such:
     * MinStack* obj = new MinStack();
     * obj->push(val);
     * obj->pop();
     * int param_3 = obj->top();
     * int param_4 = obj->getMin();
     */
    
  • class MinStack:
        def __init__(self):
            self.sk = []
            self.minsk = [inf] # trick, avoid later empty-check for min-stack
    
        def push(self, x: int) -> None:
            self.sk.append(x)
            self.minsk.append(min(x, self.minsk[-1]))
    
        def pop(self) -> None:
    		if not self.sk:
    			return
            self.sk.pop()
            self.minsk.pop()
    
        def top(self) -> int:
            return self.sk[-1]
    
        def getMin(self) -> int:
            return self.minsk[-1]
    
    
    # Your MinStack object will be instantiated and called as such:
    # obj = MinStack()
    # obj.push(x)
    # obj.pop()
    # param_3 = obj.top()
    # param_4 = obj.getMin()
    
    ############
    
    class MinStack:
    
    	def __init__(self):
    		self.sk = []
    		self.minsk = []
    
    	def push(self, val: int) -> None:
    		self.sk.append(val)
    
            # empty check
    		self.minsk.append(val if not self.minsk else min(val, self.minsk[-1]))
    
    	def pop(self) -> None:
    		if not self.sk:
    			return
    
    		self.sk.pop()
    		self.minsk.pop()
    
    	def top(self) -> int:
    		return self.sk[-1]
    
    	def getMin(self) -> int:
    		return self.minsk[-1]
    
    # optimize above, using only 1 stack, with stack element as tuple: (val, its associated min)
    class MinStack:
    
        def __init__(self):
            self._stack = []
    
        def push(self, x: int) -> None:
            cur_min = self.getMin()
            if x < cur_min:
                cur_min = x
            self._stack.append((x, cur_min))
    
        def pop(self) -> None:
            self._stack.pop()
    
        def top(self) -> int:
            if not self._stack:
                return None
            else:
                return self._stack[-1][0]
    
        def getMin(self) -> int:
            if not self._stack:
                return float('inf')
            else:
                return self._stack[-1][1]
    
    
  • type MinStack struct {
    	stk1 []int
    	stk2 []int
    }
    
    func Constructor() MinStack {
    	return MinStack{[]int{}, []int{math.MaxInt32} }
    }
    
    func (this *MinStack) Push(val int) {
    	this.stk1 = append(this.stk1, val)
    	this.stk2 = append(this.stk2, min(val, this.stk2[len(this.stk2)-1]))
    }
    
    func (this *MinStack) Pop() {
    	this.stk1 = this.stk1[:len(this.stk1)-1]
    	this.stk2 = this.stk2[:len(this.stk2)-1]
    }
    
    func (this *MinStack) Top() int {
    	return this.stk1[len(this.stk1)-1]
    }
    
    func (this *MinStack) GetMin() int {
    	return this.stk2[len(this.stk2)-1]
    }
    
    /**
     * Your MinStack object will be instantiated and called as such:
     * obj := Constructor();
     * obj.Push(val);
     * obj.Pop();
     * param_3 := obj.Top();
     * param_4 := obj.GetMin();
     */
    
  • class MinStack {
        stk1: number[];
        stk2: number[];
    
        constructor() {
            this.stk1 = [];
            this.stk2 = [Infinity];
        }
    
        push(val: number): void {
            this.stk1.push(val);
            this.stk2.push(Math.min(val, this.stk2[this.stk2.length - 1]));
        }
    
        pop(): void {
            this.stk1.pop();
            this.stk2.pop();
        }
    
        top(): number {
            return this.stk1[this.stk1.length - 1];
        }
    
        getMin(): number {
            return this.stk2[this.stk2.length - 1];
        }
    }
    
    /**
     * Your MinStack object will be instantiated and called as such:
     * var obj = new MinStack()
     * obj.push(x)
     * obj.pop()
     * var param_3 = obj.top()
     * var param_4 = obj.getMin()
     */
    
    
  • var MinStack = function () {
        this.stk1 = [];
        this.stk2 = [Infinity];
    };
    
    /**
     * @param {number} val
     * @return {void}
     */
    MinStack.prototype.push = function (val) {
        this.stk1.push(val);
        this.stk2.push(Math.min(this.stk2[this.stk2.length - 1], val));
    };
    
    /**
     * @return {void}
     */
    MinStack.prototype.pop = function () {
        this.stk1.pop();
        this.stk2.pop();
    };
    
    /**
     * @return {number}
     */
    MinStack.prototype.top = function () {
        return this.stk1[this.stk1.length - 1];
    };
    
    /**
     * @return {number}
     */
    MinStack.prototype.getMin = function () {
        return this.stk2[this.stk2.length - 1];
    };
    
    /**
     * Your MinStack object will be instantiated and called as such:
     * var obj = new MinStack()
     * obj.push(val)
     * obj.pop()
     * var param_3 = obj.top()
     * var param_4 = obj.getMin()
     */
    
    
  • public class MinStack {
        private Stack<int> stk1 = new Stack<int>();
        private Stack<int> stk2 = new Stack<int>();
        
        public MinStack() {
            stk2.Push(int.MaxValue);
        }
        
        public void Push(int x) {
            stk1.Push(x);
            stk2.Push(Math.Min(x, GetMin()));
        }
        
        public void Pop() {
            stk1.Pop();
            stk2.Pop();
        }
        
        public int Top() {
            return stk1.Peek();
        }
        
        public int GetMin() {
            return stk2.Peek();
        }
    }
    
    /**
     * Your MinStack object will be instantiated and called as such:
     * MinStack obj = new MinStack();
     * obj.Push(x);
     * obj.Pop();
     * int param_3 = obj.Top();
     * int param_4 = obj.GetMin();
     */
    
  • use std::collections::VecDeque;
    struct MinStack {
        stk1: VecDeque<i32>,
        stk2: VecDeque<i32>,
    }
    
    /**
     * `&self` means the method takes an immutable reference.
     * If you need a mutable reference, change it to `&mut self` instead.
     */
    impl MinStack {
        fn new() -> Self {
            Self { stk1: VecDeque::new(), stk2: VecDeque::new() }
        }
    
        fn push(&mut self, x: i32) {
            self.stk1.push_back(x);
            if self.stk2.is_empty() || *self.stk2.back().unwrap() >= x {
                self.stk2.push_back(x);
            }
        }
    
        fn pop(&mut self) {
            let val = self.stk1.pop_back().unwrap();
            if *self.stk2.back().unwrap() == val {
                self.stk2.pop_back();
            }
        }
    
        fn top(&self) -> i32 {
            *self.stk1.back().unwrap()
        }
    
        fn get_min(&self) -> i32 {
            *self.stk2.back().unwrap()
        }
    }/**
     * Your MinStack object will be instantiated and called as such:
     * let obj = MinStack::new();
     * obj.push(x);
     * obj.pop();
     * let ret_3: i32 = obj.top();
     * let ret_4: i32 = obj.get_min();
     */
    
    

All Problems

All Solutions