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

# 716. Max Stack

Easy

## Description

Design a max stack that supports push, pop, top, peekMax and popMax.

1. push(x) – Push element x onto stack.
2. pop() – Remove the element on top of the stack and return it.
3. top() – Get the element on the top.
4. peekMax() – Retrieve the maximum element in the stack.
5. popMax() – Retrieve the maximum element in the stack, and remove it. If you find more than one maximum elements, only remove the top-most one.

Example 1:

MaxStack stack = new MaxStack();
stack.push(5);
stack.push(1);
stack.push(5);
stack.top(); -> 5
stack.popMax(); -> 5
stack.top(); -> 1
stack.peekMax(); -> 5
stack.pop(); -> 1
stack.top(); -> 5


Note:

1. -1e7 <= x <= 1e7
2. Number of operations won’t exceed 10000.
3. The last four operations won’t be called when stack is empty.

## Solution

A stack supports push, pop, and top already, so only the last two operations need to be implemented. Use two stacks.

• One stack works as the normal stack,
• and the other stack which is called the maximum stack stores the maximum element so far.

Both stacks are initialized in the constructor. The other three functions should be modified as well.

1. The push() function. Push the element into the normal stack, and for the maximum stack, if the maximum stack is empty, then simply push the element into the maximum stack, otherwise push the maximum element between the current element and the element at the top of the maximum stack.

2. The pop() function. Simply pop both the normal stack and the maximum stack, and return the element popped from the normal stack.

3. The top() function. Simply return the top element of the normal stack.

4. The peekMax() function. Simply return the top element of the maximum stack. The reason why this works is that, each time the push function is called, the element pushed into the maximum stack is guaranteed to be the maximum element so far, so at any time, the top element of the maximum stack is the maximum element among all the elements pushed.

5. The popMax() function. This function is the most complicated one. Since the maximum element is not always at the top of the normal stack, to find the maximum element, some elements may need to be popped from the normal stack first. The top element of the normal stack is the maximum element if and only if it equals the top element of the maximum stack. After the maximum element is popped, the other popped elements need to be pushed again, so use a new stack to store the elements that were popped before finding the maximum element in the normal stack. After the maximum element is popped, for each element in the new stack, do the push operation so that both the normal stack and the maximum stack contain the correct values.

• class MaxStack {
Stack<Integer> stack;
Stack<Integer> maxStack;

/** initialize your data structure here. */
public MaxStack() {
stack = new Stack<Integer>();
maxStack = new Stack<Integer>();
}

public void push(int x) {
stack.push(x);
if (maxStack.isEmpty())
maxStack.push(x);
else {
int prev = maxStack.peek();
x = Math.max(x, prev);
maxStack.push(x);
}
}

public int pop() {
int element = stack.pop();
maxStack.pop();
return element;
}

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

public int peekMax() {
return maxStack.peek();
}

public int popMax() {
int max = maxStack.peek();
Stack<Integer> tempStack = new Stack<Integer>();
while (stack.peek() != max) {
tempStack.push(stack.pop());
maxStack.pop();
}
stack.pop();
maxStack.pop();
while (!tempStack.isEmpty())
push(tempStack.pop());
return max;
}
}

/**
* Your MaxStack object will be instantiated and called as such:
* MaxStack obj = new MaxStack();
* obj.push(x);
* int param_2 = obj.pop();
* int param_3 = obj.top();
* int param_4 = obj.peekMax();
* int param_5 = obj.popMax();
*/

• // OJ: https://leetcode.com/problems/max-stack/
// Time:
//      MaxStack, top, peekMax: O(1)
//      push: log(N)
//      pop, popMax: O(logN) amortized
// Space: O(N)
class MaxStack {
map<int, vector<int>> m;
vector<int> v;
void pop(int n) {
int i = m[n].back();
v[i] = INT_MIN;
m[n].pop_back();
if (m[n].empty()) m.erase(n);
while (v.size() && v.back() == INT_MIN) v.pop_back();
}
public:
MaxStack() {}
void push(int x) {
m[x].push_back(v.size());
v.push_back(x);
}
int pop() {
int n = v.back();
pop(n);
return n;
}
int top() {
return v.back();
}
int peekMax() {
return m.rbegin()->first;
}
int popMax() {
int n = peekMax();
pop(n);
return n;
}
};

• class MaxStack(object):

def __init__(self):
"""
"""
self.stack = []
self.max_stack = []

def push(self, x):
"""
:type x: int
:rtype: void
"""
self.stack.append(x)
if len(self.max_stack) == 0:
self.max_stack.append(x)
return
if self.max_stack[-1] > x:
self.max_stack.append(self.max_stack[-1])
else:
self.max_stack.append(x)

def pop(self):
"""
:rtype: int
"""
if len(self.stack) != 0:
self.max_stack.pop(-1)
return self.stack.pop(-1)

def top(self):
"""
:rtype: int
"""
return self.stack[-1]

def peekMax(self):
"""
:rtype: int
"""
if len(self.max_stack) != 0:
return self.max_stack[-1]

def popMax(self):
"""
:rtype: int
"""
val = self.peekMax()
buff = []
while self.top() != val:
buff.append(self.pop())
self.pop()
while len(buff) != 0:
self.push(buff.pop(-1))
return val