Min stack

LeetCode Problem: 155. Min Stack

## Problem description

Design a stack that supports push, pop, top, and retrieving the minimum element in constant time.

* **`push(x)`** – Push element `x` onto stack.
* **`pop()`** – Removes the element on top of the stack.
* **`top()`** – Get the top element.
* **`getMin()`** – Retrieve the minimum element in the stack.

### 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

* Methods `pop`, `top` and `getMin` operations will always be called on **non-empty** stacks.

## Approach 1: data stack with min stack (O(n) auxiliary space)

### Data structure

* Keep a **data stack** to record all the data.
* Keep a **min stack** to record the min values pushed into the stack.

### Push

When we push a new element, we compare this with the current minimum value on the min stack.

* **Corner case**: If the stack is empty, then we do not need to compare, but just push one element to both the data stack and the min stack.
* Multiple instances of min: For the purpose of keeping multiple instances of min, every time when we push an element onto the data stack, we push the minimum value to the min stack.
	+ For example: If data is 5 → 4 → 1 → 1 → 2 → 2 → 1 → -1 → -1， then the min stack is 5 → 4 → 1 → 1 → 1 → 1 → 1 → -1 → -1.

Time complexity
**O(1)**, since we do the push on the stack once for each, each with time complexity O(1).
Space complexity
The space complexity for storing the data is **O(n)**, since we use exactly twice as much space as we have for the data.
### Pop

We obtain access to the first element to pop off with the current minimum value on the min stack.

* **Corner case**: If the stack is empty, then we do not need to do anything.

Then we can pop from the top of the data stack as well as the min stack.

Time complexity
**O(1)**, since we do the pop on the stack once for each, each with time complexity O(1).
### Get minimum value

Time complexity
This can be done in **O(1)** time complexity as we get the top (minimum value) of the min stack.

## Approach 1A: Refinement of approach 1

### Data structure

Similar to approach 1, we can use a **data stack** and a **min stack**.

But this time each element in the min stack is a pair:

* `min`: the minimum value.
* `count`: a counter to record how many times that minimum value has been pushed into the data stack.

### Push

* Should the minimum value be updated, we add a new entry to the min stack, and set its count to 1.
* If the minimum value does not change, add the count by 1.

Time complexity
**O(1)**, since we take constant time for both pushing to the data stack and updating the min stack.
Space complexity
**O(n)** for both the data stack and the min stack.
### Pop

* If the count of the current min value on the min stack is 1, then this entry is deleted.
* Otherwise, we just decrease the counter by 1.

Time complexity
**O(1)**, since we take constant time for both popping from the data stack and updating the min stack.
### Get minimum value

Time complexity
Again, this can be done in **O(1)** time complexity as we get the top (minimum value) of the min stack.

## Approach 1B: Refinement of approach 1A (do not use a counter)

### Data structure

The data structure is similar to approach 1A: a **data stack** and a **min stack**.

But we make some changes to the **min stack**:

* `min`: the minimum value.
* `pos`: a position at which this minimum value occurred *first*.

The first element on the min stack has its `pos` value 0, corresponding to the index 0 on the data stack.

### Push

* Whenever we get a new minimum value, we record the position of this element that first appears on the stack.
* If we are not inserting a new minimum value (e.g. inserting 2 when the minimum is 1), we do not do anything on the min stack.

Time complexity
**O(1)** for the push actions on both the data stack and the min stack.
Space complexity
**O(n)** for both the data stack and the min stack.
### Pop

We compare the index of the element to be popped (equals size of stack minus 1) and the `pos` field of the min value on the min stack.

* If the index of this element equals the `pos` field of the min value on the min stack, then pop the entry from the min stack.
* Otherwise, we do not do anything on the min stack

Time complexity
**O(1)** for the pop actions on both the data stack and the min stack.
### Get minimum value

Time complexity
Again, this can be done in **O(1)** time complexity as we get the top (minimum value) of the min stack.
### C++ solution

```
class MinStack {
private:
 class MinEntry {
 public:
 int val;
 int pos;

 MinEntry(int val = 0, int pos = 0): val(val), pos(pos) {}
 };

 std::stack<int> dataStack;
 std::stack<MinEntry> minStack;

public:
 /\*\* initialize your data structure here. \*/
 MinStack() {
 this->dataStack = std::stack<int>();
 this->minStack = std::stack<MinEntry>();
 }

 void push(int x) {
 // push to data stack
 dataStack.emplace(x);
 // push to min stack if there is a new min value
 if (minStack.empty()) {
 minStack.emplace(MinEntry(x));
 }
 else {
 if (x < minStack.top().val) {
 int pos = dataStack.size() - 1;
 minStack.emplace(MinEntry(x, pos));
 }
 }
 }

 void pop() {
 // trivial case
 if (dataStack.empty()) {
 return;
 }

 // pop from min stack
 int pos = dataStack.size() - 1;
 MinEntry minTop = minStack.top();
 if (pos == minTop.pos) {
 minStack.pop();
 }
 // pop from data stack
 dataStack.pop();
 }

 int top() {
 return dataStack.top();
 }

 int getMin() {
 return minStack.top().val;
 }
};

/\*\*
 \* 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();
 \*/

```

### Java solution

```
class MinStack {

 private static class MinEntry {
 public int val = 0;
 public int pos = 0;

 public MinEntry(int val, int pos) {
 this.val = val;
 this.pos = pos;
 }
 }

 private ArrayDeque<Integer> dataStack;
 private ArrayDeque<MinEntry> minStack;

 /\*\* initialize your data structure here. \*/
 public MinStack() {
 this.dataStack = new ArrayDeque<>();
 this.minStack = new ArrayDeque<>();
 }

 public void push(int x) {
 // add to data stack
 dataStack.offerLast(x);
 // add to min stack, if the min has updated
 if (minStack.isEmpty()) {
 minStack.offerLast(new MinEntry(x, 0));
 }
 else {
 if (x < minStack.peekLast().val) {
 int pos = dataStack.size() - 1;
 minStack.offerLast(new MinEntry(x, pos));
 }
 }
 }

 public void pop() {
 // trivial case: pop from empty stack
 if (dataStack.isEmpty()) {
 return;
 }

 // pop from min stack if we are popping the last copy of min value
 int pos = dataStack.size() - 1;
 MinEntry minEntry = minStack.peekLast();
 if (pos == minEntry.pos) {
 minStack.pollLast();
 }
 // pop from data stack
 dataStack.pollLast();
 }

 public int top() {
 return dataStack.peekLast();
 }

 public int getMin() {
 return minStack.peekLast().val;
 }
}

/\*\*
 \* 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();
 \*/

```

## Programming notes

### Java

* The `ArrayDeque` class: Class `ArrayDeque<E>`

## External links

* Design a stack that supports `getMin()` in **O(1)** time and **O(1)** extra space (Archive)