题目
Design a max stack that supports push, pop, top, peekMax and popMax.
- push(x) – Push element x onto stack.
- pop() – Remove the element on top of the stack and return it.
- top() – Get the element on the top.
- peekMax() – Retrieve the maximum element in the stack.
- 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.
分析
类似于155. Min Stack,但是多了popMax()操作,这是本题的难点。popMax()操作需要弹出最大栈中最大的值,并且保持最大栈中元素的大小关系。关键在于:如何维护一个辅助最大栈,记录每次变更后的最大值。思考问题:
- 对于push()操作,如何维护辅助最大栈?
- 对于popMax()操作,最大值可能在最大栈的最底层,此时如何弹出?弹出后如何维护最大栈与辅助最大栈?
对于第1点,操作和[155. Min Stack]完全相同。
对于第2点,需要再开一个临时栈,临时存放被弹出最大值上面的若干元素。
代码如下:
//
// Created by simida on 2020/07/12.
//
// 加锁题,未经OJ测试
// time complexity
// space complexity O(n)
#include <stdio.h>
#include <iostream>
#include <stack>
using namespace std;
class MaxStack {
private:
stack<int> stack_; // 最大值栈
stack<int> help_stack_; // 辅助最大值栈
public:
/** initialize your data structure here. */
MaxStack() {
}
// O(1)
void push(int x) {
stack_.push(x);
if (help_stack_.empty()) {
help_stack_.push(x);
} else if (x > help_stack_.top()) {
help_stack_.push(x);
} else {
int top = help_stack_.top();
help_stack_.push(top);
}
}
// O(1)
void pop() {
stack_.pop();
help_stack_.pop();
}
// O(1)
int top() {
return stack_.top();
}
// O(1)
int peekMax() {
return help_stack_.top();
}
// O(n)
int popMax() {
stack<int> s; // 临时栈
int top = help_stack_.top();
// 将最大值上面的元素放入临时栈,然后弹出最大值即可
while (stack_.top() != top) {
s.push(stack_.top());
stack_.pop();
}
stack_.pop(); // 将stack_最顶端的最大值弹出
// 将辅助最大值栈help_stack_的最大值弹出
while (!help_stack_.empty() && help_stack_.top() == top) { // //特别注意: 这里的empty判断不能丢掉,否则可能访问空栈的栈顶元素,程序报错。
help_stack_.pop();
}
// 对于stack_: 将临时栈s中的元素重新放回stack_中
// 对于help_stack_: 重新生成辅助最大值栈
while (!s.empty()) {
push(s.top());
s.pop();
}
return top;
}
};
int main() {
// Your MaxStack object will be instantiated and called as such:
MaxStack* obj = new MaxStack();
obj->push(5);
printf("top is %d\n", obj->top()); // 5
obj->push(4);
printf("top is %d\n", obj->top()); // 4
obj->push(3);
printf("top is %d\n", obj->top()); // 3
obj->push(2);
printf("top is %d\n", obj->top()); // 2
obj->push(1);
printf("top is %d\n", obj->top()); // 1
printf("\nstop push\n");
obj->popMax();
printf("top is %d\n", obj->top()); // 1
printf("peekMax is %d\n", obj->peekMax()); // 4
obj->popMax();
printf("top is %d\n", obj->top()); // 1
printf("peekMax is %d\n", obj->peekMax()); // 3
obj->popMax();
printf("top is %d\n", obj->top()); // 1
printf("peekMax is %d\n", obj->peekMax()); // 2
obj->pop();
printf("top is %d\n", obj->top()); // 2
}