请你设计一个 最小栈 。它提供 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。

实现 MinStack 类:

MinStack() 初始化堆栈对象。

void push(int val) 将元素val推入堆栈。

void pop() 删除堆栈顶部的元素。

int top() 获取堆栈顶部的元素。

int getMin() 获取堆栈中的最小元素。

示例 1:

输入:
[“MinStack”,“push”,“push”,“push”,“getMin”,“pop”,“top”,“getMin”]
[[],[-2],[0],[-3],[],[],[],[]]

输出:
[null,null,null,null,-3,null,0,-2]

解释:
MinStack minStack = new MinStack();
minStack.push(-2);
minStack.push(0);
minStack.push(-3);
minStack.getMin(); --> 返回 -3.
minStack.pop();
minStack.top(); --> 返回 0.
minStack.getMin(); --> 返回 -2.

提示:

-2(31) <= val <= 2(31) - 1

pop、top 和 getMin 操作总是在 非空栈 上调用

push、pop、top 和 getMin 最多被调用 3 * 10(4) 次

可以使用辅助栈来存放当前最小值,当新入栈元素小于等于当前最小值时才入辅助栈,当出栈元素等于当前最小值时才出辅助栈,思想类似于单调栈,即后入栈还大的元素没必要记录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class MinStack {
public:
/** initialize your data structure here. */
stack<int> a;
stack<int> minS;
MinStack() {}

void push(int x) {
a.push(x);
if (minS.empty() || x <= minS.top())
minS.push(x);
}
void pop() {
int mid = a.top();
a.pop();
if (mid == minS.top())
minS.pop();
}
int top() { return a.top(); }
int getMin() { return minS.top(); }
};

也可以不使用辅助栈,想快速获得最小值,维护当前最小值是必须的,所以原始栈就不能保存原始元素,要想办法与最小值建立联系

很容易想到x-minL,当 minL<x 时,可通过a.top()+minL获得x

当minL>x时,a.top()就是 旧的minL-x,此处x为新的minL,此时出栈需要更新minL为minL-a.top()

当minL=x时,a.top()=0

上面minL与x的分类讨论也即a.top()与0的分类讨论

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
class MinStack {
public:
/** initialize your data structure here. */
stack<long> a;
long minL;
MinStack() {}

void push(int x) {
if (a.empty()) {
a.push(0);
minL = x;
} else {
a.push((long)x - minL);
minL = min(minL, (long)x);
}
}

void pop() {
if (a.top() < 0)
minL = minL - a.top();
a.pop();
}

int top() {
if (a.top() < 0)
return minL;
else
return a.top() + minL;
}
int getMin() { return minL; }
};