leetcode 716

问题

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:

1
2
3
4
5
6
7
8
9
10
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.

分析

这道题中一开始没有说清楚,还以为和MinStack那道题类似,直接用两个栈解决即可。后来发现popMax函数只会把栈中最大的元素pop出来,而其他元素还都留在栈中。这样的话就不能使用stack等线性表来实现了,改用双向链表list来实现。然后在通过一个 map\::iterator>> 来保存每个值对应的双向链表的地址。map默认为从小到大的排序。因此,在popMax的时候,只需要将map的最后一个元素对应的栈取一个栈顶,并将其在list中移除即可。

代码

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
class MaxStack {
public:
list<int> l; // simulate stack
map<int, stack<list<int>::iterator>> mp;
/** initialize your data structure here. */
MaxStack() {
l.clear();
mp.clear();
}

void push(int x) {
l.push_back(x);
auto it = l.end();
mp[x].push(--it);
}

int pop() {
int x = l.back();
l.pop_back();
mp[x].pop();
if (mp[x].size() == 0)
mp.erase(x);
return x;
}

int top() {
return l.back();
}

int peekMax() {
auto it = mp.end();
return (--it)->first;
}

int popMax() {
auto it = mp.end();
int x = (--it)->first;
l.erase(it->second.top());
it->second.pop();
if (it->second.size() == 0)
mp.erase(it);
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();
*/