剑指 offer 30 包含 min 函数的栈
方法一
在入栈和出栈的时候最小值都可能发生变化,因此,在入栈和出栈之后都要对最小值进行更改。push 时最简单,只需要将入栈的元素和minValue进行比较,如果比 minValue小就更改 minValue的值即可,入栈时间复杂度是 O ( 1 ) O(1) O(1)。出栈稍复杂些,如果出栈的元素不是最小值,则不用进行任何处理;否则,就需要重新寻找最小值,这里出栈的时间复杂度不是 O ( 1 ) O(1) O(1)。min 函数,直接返回最小值即可。
class MinStack {
Stack <Integer> s = null ;
int minValue;
/** initialize your data structure here. */
public MinStack() {
this.s = new Stack<>();
this.minValue = Integer.MAX_VALUE;
}
public void push(int x) {
this.s.push(x);
if(minValue>x){
minValue = x;
}
}
public void pop() {
this.s.pop();
if(!this.s.contains(minValue)){
minValue = Integer.MAX_VALUE;
for(int tmp:s){
if(minValue>tmp){
minValue = tmp;
}
}
}
}
public int top() {
return this.s.peek();
}
public int min() {
return minValue;
}
}
/**
* 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();
*/
方法二
方法一只添加了一个成员变量存放最小元素,这是不够的,因为当最小元素刚好是栈顶元素,恰好又执行了出栈操作,就要重新寻找最小元素,这时就要遍历栈中所有元素时间复杂度是
O
(
n
)
O(n)
O(n),不符合出栈时间复杂度是
O
(
1
)
O(1)
O(1)的要求。
在最小元素被弹出栈的时候,我们希望能够得到次小元素。考虑把每次的最小元素(之前的最小元素和新入栈的元素两者的较小值)都保存起来放到另外一个辅助栈里。
如果每次都把最小元素压入辅助栈,那么就能保证辅助栈的栈顶一直都是最小的元素,当最小元素从数据栈内被弹出之后,同时弹出辅助栈的栈顶元素,,此时辅助栈的新栈顶元素就是下一个最小值。
class MinStack {
Stack <Integer> s;
Stack<Integer> s1;
/** initialize your data structure here. */
public MinStack() {
this.s = new Stack<>();
this.s1 = new Stack<>();
}
public void push(int x) {
if(s.empty()){
s.push(x);
s1.push(x);
}else{
if(x<s1.peek()){
s1.push(x);
}else{
s1.push(s1.peek());
}
s.push(x);
}
}
public void pop() {
s.pop();
s1.pop();
}
public int top() {
return s.peek();
}
public int min() {
return s1.peek();
}
}
/**
* 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();
*/
时间复杂度
O
(
1
)
O(1)
O(1)。
空间复杂度
O
(
N
)
O(N)
O(N),需要维持一个保存最小元素的辅助栈。