Question

Formatted question description: https://leetcode.ca/all/155.html

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.

Algorithm

Two stacks are used to achieve this, one stack is used to store the data that push in in order, and the other is used to store the smallest value that has occurred.

Code

• class MinStack {

Stack<Integer> sk = new Stack<>();
Stack<Integer> min = new Stack<>();

public void push(int x) {
sk.push(x);
// @note: if pushing duplicated, then the 2nd is missing if no "="
if (min.isEmpty() || min.peek() >= x) {
min.push(x);
}
}

public void pop() {
int popVal = sk.pop();
if (popVal == min.peek()) {
min.pop();
}
}

public int top() {
return sk.peek();
}

public int getMin() {
return min.peek();
}

}

class MinStack_SortedList_ACed {

Stack<Integer> sk;
PriorityQueue<Integer> sorted;

/** initialize your data structure here. */
public MinStack_SortedList_ACed() {
sk = new Stack<>();
sorted = new PriorityQueue<>();
}

public void push(int x) {
sk.push(x);
sorted.offer(x); // NlogN
}

public void pop() {
int popped = sk.pop();

// remove by object, not by index
// but, here remove() is o(N) operation
sorted.remove(popped);
}

public int top() {
return sk.peek();
}

public int getMin() {
return sorted.peek();
}
}

############

class MinStack {
private Deque<Integer> stk1 = new ArrayDeque<>();
private Deque<Integer> stk2 = new ArrayDeque<>();

/** initialize your data structure here. */
public MinStack() {
stk2.push(Integer.MAX_VALUE);
}

public void push(int x) {
stk1.push(x);
stk2.push(Math.min(x, 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(x);
* obj.pop();
* int param_3 = obj.top();
* int param_4 = obj.getMin();
*/

• // OJ: https://leetcode.com/problems/min-stack/
// Time: O(1) for all
// Space: O(N)
class MinStack {
stack<int> mn, val;
public:
MinStack() {}
void push(int x) {
val.push(x);
if (mn.empty() || mn.top() >= x) mn.push(x);
}
void pop() {
if (val.top() == mn.top()) mn.pop();
val.pop();
}
int top() {
return val.top();
}
int getMin() {
return mn.top();
}
};

• class MinStack:
def __init__(self):
self.sk = []
self.minsk = [inf] # trick, avoid later None 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)
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
}

/** initialize your data structure here. */
func Constructor() MinStack {
return MinStack{[]int{}, []int{math.MaxInt32} }
}

func (this *MinStack) Push(x int) {
this.stk1 = append(this.stk1, x)
this.stk2 = append(this.stk2, min(x, 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]
}

func min(a, b int) int {
if a < b {
return a
}
return b
}

/**
* Your MinStack object will be instantiated and called as such:
* obj := Constructor();
* obj.Push(x);
* obj.Pop();
* param_3 := obj.Top();
* param_4 := obj.GetMin();
*/

• class MinStack {
stk1: number[];
stk2: number[];

constructor() {
this.stk1 = [];
this.stk2 = [Infinity];
}

push(x: number): void {
this.stk1.push(x);
this.stk2.push(Math.min(x, 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()
*/


• /**
* initialize your data structure here.
*/
var MinStack = function () {
this.stack = [];
this.minStack = [];
};

/**
* @param {number} x
* @return {void}
*/
MinStack.prototype.push = function (x) {
this.stack.unshift(x);
if (!this.minStack.length || this.minStack[0] >= x) {
this.minStack.unshift(x);
}
};

/**
* @return {void}
*/
MinStack.prototype.pop = function () {
if (this.stack.shift() === this.minStack[0]) {
this.minStack.shift();
}
};

/**
* @return {number}
*/
MinStack.prototype.top = function () {
return this.stack[0];
};

/**
* @return {number}
*/
MinStack.prototype.min = function () {
return this.minStack[0];
};

/**
* 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.min()
*/


• public class MinStack {
private Stack<int> stk1 = new Stack<int>();
private Stack<int> stk2 = new Stack<int>();

/** initialize your data structure here. */
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 {
stack: VecDeque<i32>,
min_stack: VecDeque<i32>,
}

/**
* &self means the method takes an immutable reference.
* If you need a mutable reference, change it to &mut self instead.
*/
impl MinStack {

/** initialize your data structure here. */
fn new() -> Self {
Self { stack: VecDeque::new(), min_stack: VecDeque::new() }
}

fn push(&mut self, x: i32) {
self.stack.push_back(x);
if self.min_stack.is_empty() || *self.min_stack.back().unwrap() >= x {
self.min_stack.push_back(x);
}
}

fn pop(&mut self) {
let val = self.stack.pop_back().unwrap();
if *self.min_stack.back().unwrap() == val {
self.min_stack.pop_back();
}
}

fn top(&self) -> i32 {
*self.stack.back().unwrap()
}

fn get_min(&self) -> i32 {
*self.min_stack.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();
*/