Description
定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的 min 函数在该栈中,调用 min、push 及 pop 的时间复杂度都是 O(1)。
Solution
光靠一个栈必然是无法实现O(1)查询min的,故我们考虑再加一个栈
在维护一个正常的栈sta1的同时,维护一个非减的栈sta2(top是最小值之一)
每次查询min的值时即为栈sta2顶的值
为什么这样是正确的?
假设当前需要push的值为x, 而sta2栈顶的值为y:
若x > y,按照我们的设计,x不需要压入sta2栈中, 因为在栈中位置更靠底部的y都将比x更晚被pop出,故x值无论在不在栈中,都对其min值无影响(影响被更小且更底部的y值所完全覆盖);
反之则将x push进sta2栈中;
pop时,若需要pop的值x等于sta2栈顶的值y,说明x在push时同时也push进了sta2栈中,所以将y也从sta2中pop出。
因此,我们实现了O(1)时间复杂度调用min、push及pop函数,实际上也就是用空间(需要另开一个栈)换时间
Code
class MinStack {
public:
/** initialize your data structure here. */
static const int maxn = 2e4 + 7;
int sta1[maxn], tail1;
int sta2[maxn], tail2;
MinStack() {
tail1 = tail2 = 0;
sta1[tail1] = sta2[tail2] = 0;
}
void push(int x) {
sta1[tail1++] = x;
if(!tail2) sta2[tail2++] = x;
else if(x <= sta2[tail2-1]) sta2[tail2++] = x;
}
void pop() {
if(tail1 == 0) return ;
int x = sta1[tail1-1];
tail1--;
if(sta2[tail2-1] == x) tail2--;
}
int top() {
return sta1[tail1-1];
}
int min() {
return sta2[tail2-1];
}
};
/**
* Your MinStack object will be instantiated and called as such:
* MinStack* obj = new MinStack();
* obj->push(x);
* obj->pop();
* int param_3 = obj->top();
* int param_4 = obj->min();
*/