716. Max Stack

716. Max Stack

Description

Design a max stack data structure that supports the stack operations and supports finding the stack’s maximum element.

Implement the MaxStack class:

  • MaxStack() Initializes the stack object.
  • void push(int x) Pushes element x onto the stack.
  • int pop() Removes the element on top of the stack and returns it.
  • int top() Gets the element on the top of the stack without removing it.
  • int peekMax() Retrieves the maximum element in the stack without removing it.
  • int popMax() Retrieves the maximum element in the stack and removes it. If there is more than one maximum element, only remove the top-most one.

You must come up with a solution that supports O(1) for each top call and O(logn) for each other call.

Example 1:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Input

["MaxStack", "push", "push", "push", "top", "popMax", "top", "peekMax", "pop", "top"]
[[], [5], [1], [5], [], [], [], [], [], []]
Output

[null, null, null, null, 5, 5, 1, 5, 1, 5]

Explanation

MaxStack stk = new MaxStack();
stk.push(5); // [**5** ] the top of the stack and the maximum number is 5.
stk.push(1); // [5, **1** ] the top of the stack is 1, but the maximum is 5.
stk.push(5); // [5, 1, **5** ] the top of the stack is 5, which is also the maximum, because it is the top most one.
stk.top(); // return 5, [5, 1, **5** ] the stack did not change.
stk.popMax(); // return 5, [5, **1** ] the stack is changed now, and the top is different from the max.
stk.top(); // return 1, [5, **1** ] the stack did not change.
stk.peekMax(); // return 5, [5, **1** ] the stack did not change.
stk.pop(); // return 1, [**5** ] the top of the stack and the max element is now 5.
stk.top(); // return 5, [**5** ] the stack did not change.

Constraints:

  • -10^7 <= x <= 10^7
  • At most 10^5calls will be made to push, pop, top, peekMax, and popMax.
  • There will be at least one element in the stack when pop, top, peekMax, or popMax is called.

Hints/Notes

Solution

Language: C++

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
class MaxStack {
public:
// the idea here is lazy priority queue
// i.e. when we remove one item, we don't really remove it from the queue
// we marked it as deleted, and during pop/other operation we check
priority_queue<pair<int, int>> pq;
unordered_set<int> removed;
stack<pair<int, int>> stk;
int idx = 0;
MaxStack() {

}

void push(int x) {
pq.push({x, idx});
stk.push({x, idx});
idx++;
}

int pop() {
top();
auto [x, idx] = stk.top();
removed.insert(idx);
stk.pop();
return x;
}

int top() {
while (removed.contains(stk.top().second)) {
stk.pop();
}
return stk.top().first;
}

int peekMax() {
while (removed.contains(pq.top().second)) {
pq.pop();
}
return pq.top().first;
}

int popMax() {
peekMax();
auto [x, idx] = pq.top();
removed.insert(idx);
pq.pop();
return x;
}
};

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