法1:双栈 再开一个栈,记录单调递减序列,关键是push操作,维护两个栈,每次push元素的时候与第二个栈的栈顶元素比较,若是较小,则进入第二个栈;若是较大,则第二个栈的栈顶元素再次入栈。于是,每次访问最小值即访问第二个栈的栈顶。
#include <stack>
class Solution {
public:
stack<int> s1;
stack<int> minS;
void push(int value) {
if(s1.empty() && minS.empty()){
s1.push(value);
minS.push(value);
}else{
s1.push(value);
if(value <= minS.top()){
minS.push(value);
}else{
minS.push(minS.top());
}
}
}
void pop() {
s1.pop();
minS.pop();
}
int top() {
return s1.top();
}
int min() {
return minS.top();
}
};
法2:类似前缀和的做法 能做到空间复杂度和时间复杂度都是O1。
在栈中存储 差值 而非原始值,并通过差值还原最小值和原始值。
- 存储差值:每次 push(x) 时,存储 x – current_min(当前最小值)。
- 更新最小值:如果 x < current_min,则更新 current_min = x。
- 恢复原始值: 当 pop 时,通过差值和 current_min 还原原始值。 如果弹出的差值 diff ≤ 0,说明该元素是当前最小值,需反向更新 current_min。
#include <stack>
class Solution {
public:
stack<int> s1;
int curMin = INT_MAX;
void push(int value) {
if(s1.empty()){
// 为空,残差为0
s1.push(0);
curMin = value;
}else{
int diff = value - curMin;
s1.push(diff);
if(diff < 0){ // 说明更小
curMin = value;
}
}
}
void pop() {
int diff = s1.top();
s1.pop();
if(diff < 0){
// 还原上一个最小值,由diff = value - curMin;变换来
curMin = curMin - diff;
}
}
int top() {
int diff = s1.top();
if(diff >= 0) return diff + curMin;
else{
return curMin; // 当前元素过程中的某个最小值
}
}
int min() {
return curMin;
}
};