题目描述
定义栈的数据结构,请在该类型中实现一个能够得到栈最小元素的min函数。调用min、push及pop的时间复杂度都是O(1)。
方法一
考虑使用两个栈,一个数据栈(就是普通的栈),实现栈的push、pop等操作;另一个辅助栈用来存放每次栈操作时(包括入栈和出栈)栈中最小元素。
辅助栈的操作:栈顶元素为当前栈中的最小元素
- 要获取当前栈中最小元素,只需要返回栈顶元素即可;
- 每次执行push操作,检查push的元素与栈顶元素的大小关系。将较小的元素push到辅助栈中。
- 当执行pop操作的时候,将辅助栈中的栈顶元素pop出去。
实例:
代码
class Solution {
public:
stack<int> data;
stack<int> minNum;
void push(int value) {
data.push(value);
if( minNum.empty() )
minNum.push(value);
else
minNum.push( minNum.top()<value?minNum.top():value );
}
void pop() {
// assert( !data.empty() && !minNum.empty() );
data.pop();
minNum.pop();
}
int top() {
return data.top();
}
int min() {
return minNum.top();
}
};
简单优化:对于辅助栈的操作,每次执行push操作时,检查push的元素是否小于或等于辅助栈栈顶元素。如果是,则也push该元素到辅助栈中。当执行pop操作的时候,检查pop的元素是否与当前最小值相等。如果相同,则需要将该元素从辅助栈中pop出去。其余情况对于辅助栈可以不做修改。
方法二
解法利用存储差值而不需要辅助栈,方法比较巧妙。该方法需要额外使用占用一个空间存储当前栈中的最小值,将最小值一直储存在栈顶。- 当需要push进一个新值value时,先将最小值pop出来,在栈中压入value与当前栈中最小元素的差值,然后比较value与当前栈中最小元素大小,将它们中间的较小值压入栈。
- 执行min()函数时,直接返回栈顶元素即可。
- 执行top()函数时,返回栈顶两个元素的和即可。
- 执行pop()函数时,先pop出栈顶的两个值,这两个值分别是当前栈中最小值min和最后压入的元素与栈中最小值的差值diff,因为pop()函数需要把最后存入的值删除,所以只需要考虑pop后的最小值min是多少,并将其压入栈中。如果diff<0,则表示最后压入栈的元素是最小的元素,因此只需将min-diff压入栈中,min-diff就是当前元素弹出后,栈中剩下元素的最小值。而如果diff>=0且栈不为空,则表示当前值不是最小值,所以需要在栈中压入最小值min。
clear(): [ ]
push(3): [3 3]
push(4): [3 1 3]
push(2): [3 1 -1 2]
push(5): [3 1 -1 3 2]
push(1): [3 1 -1 3 -1 1]
push(1): [3 1 -1 3 -1 0 1]
push(6): [3 1 -1 3 -1 0 5 1]
push(7): [3 1 -1 3 -1 0 5 6 1]
min() --> 1; pop() --> 7: [3 1 -1 3 -1 0 5 1]
min() --> 1; pop() --> 6: [3 1 -1 3 -1 0 1]
min() --> 1; pop() --> 1: [3 1 -1 3 -1 1]
min() --> 1; pop() --> 1: [3 1 -1 3 2]
min() --> 2; pop() --> 5: [3 1 -1 2]
min() --> 2; pop() --> 2: [3 1 3]
min() --> 3; pop() --> 4: [3 3]
min() --> 4; pop() --> 3: [ ]
代码
class Solution {
public:
stack<int> data;
void push(int value) {
if( data.empty() )
{
data.push(value);
data.push(value);
return;
}
int min = data.top();
data.pop();
if( min <= value )
{
data.push(value-min);
data.push(min);
return;
}
else
{
data.push(value-min);
data.push(value);
return;
}
return;
}
void pop() {
int min = data.top();
data.pop();
if( data.top() >= 0 )
{
data.pop();
data.push(min);
return;
}
else
{
int temp = data.top();
data.pop();
data.push(min-temp);
}
return;
}
int top() {
int min = data.top();
data.pop();
int res = data.top()+min;
data.push(min);
return res;
}
int min() {
return data.top();
}
};
参考文献:
https://www.cnblogs.com/javawebsoa/archive/2013/05/21/3091727.html
https://blog.csdn.net/sgbfblog/article/details/7752878