题目链接:Min Stack
Design a stack that supports push, pop, top, and retrieving the minimum element in constant time.
- push(x) – Push element x onto stack.
- pop() – Removes the element on top of the stack.
- top() – Get the top element.
- getMin() – Retrieve the minimum element in the stack.
这道题的要求是实现一种数据结构,使其在实现栈的功能的同时又能以O(1)时间返回最小值,并支持push(x)、pop()、top()、getMin()四种操作。
思路就是用1个栈s完成栈的操作,再利用一个栈mins维护最小值(其栈顶就为数据的最小值):
- push(x):将元素压入s中,同时比较x与mins的栈顶元素(如果民生为空,直接压入mins中)大小,将小的压入mins中;
- pop():s和mins中均弹出元素即可;
- top():返回s中的栈顶元素;
- getMin():返回mins中的栈顶元素。
压栈的详细过程如下:
例如依次压入2、4、1、3,那么
压入2后:
| 2 | | 2 |
|---| |---|
s mins
压入4后:
| 4 | | 2 |
| 2 | | 2 |
|---| |---|
s mins
压入1后:
| 1 | | 1 |
| 4 | | 2 |
| 2 | | 2 |
|---| |---|
s mins
压入3后:
| 3 | | 1 |
| 1 | | 1 |
| 4 | | 2 |
| 2 | | 2 |
|---| |---|
s mins
不过上面有一个问题,细心观察就可以发现,就是mins中的1和2发生了重复,造成了空间浪费。要想避免这种浪费,可以对push和pop操作稍做处理:
- push(x):将元素压入s中,而只有当mins为空或者mins的栈顶元素大于等于x的时候才压入栈,这样就可以避免重复在mins中压入相同的最小值;
- pop():s中弹出元素,而只有在mins的栈顶元素与s中要弹栈的元素相等的时候,mins才弹栈,因为此时说明mins中的栈顶元素是在s中压入栈之后的最小值,需要弹出。
这样,对于上面那个例子,情况如下:
例如依次压入2、4、1、3,那么
压入2后:
| 2 | | 2 |
|---| |---|
s mins
压入4后(由于4大于mins的栈顶元素2,因此mins不进行压栈操作):
| 4 |
| 2 | | 2 |
|---| |---|
s mins
压入1后(由于1小于mins的栈顶元素2,因此把1压入mins中):
| 1 |
| 4 | | 1 |
| 2 | | 2 |
|---| |---|
s mins
压入3后(同上面压入4情形,mins不进行压栈操作):
| 3 |
| 1 |
| 4 | | 1 |
| 2 | | 2 |
|---| |---|
s mins
而对于弹栈操作:
1次pop后(由于s的栈顶元素于mins的栈顶元素不同,因此mins不进行弹栈操作):
| 1 |
| 4 | | 1 |
| 2 | | 2 |
|---| |---|
s mins
2次pop后(由于s的栈顶元素于mins的栈顶元素相同,因此mins需要弹栈操作):
| 4 |
| 2 | | 2 |
|---| |---|
s mins
3次pop后:
| 2 | | 2 |
|---| |---|
s mins
4次pop后:
|---| |---|
s mins
时间复杂度:O(n)
空间复杂度:O(n)
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
class MinStack
{
stack<int> s;
stack<int> mins;
public:
void push(int x)
{
if(mins.empty() || x <= mins.top())
mins.push(x);
s.push(x);
}
void pop()
{
if(s.top() == mins.top())
mins.pop();
s.pop();
}
int top()
{
return s.top();
}
int getMin()
{
return mins.top();
}
};