题目:
实现一个特殊的栈,在实现基本功能的基础上,再实现返回栈中最小元素的操作。
描述:
用两个栈,一个栈用来保存当前栈中的元素,其功能和一个正常的栈没有什么区别,记作stackData;另一个栈用来保存每一步的最小值,这个栈记作stackMin。
方法一:
压入数据规则:
假设当前数据为 newNum, 现将其压入 stackData。然后判断 stackMin 是否为空:
- 如果为空:则 newNum 也压入 stackMin 。
- 如果不为空:则比较 newNum 和 stackMin 栈顶元素中哪一个更小:
- 如果 newNum更小或是两者相等,则 newNum 也压入 stackMin;
- 如果 stackMin 中栈顶元素更小,则 stackMin 不压入任何内容;
举例:依次压入 3、4、5、1、2、1的过程,stackData 和 stackMin 的变化如下:
弹出数据规则:
先在 stackData 中弹出栈顶元素,记作 value。然后比较 stackMin 栈顶元素 和 value 哪一个更小。
当 value 等于 stackMin 栈顶元素时,stackMin弹出栈顶元素;当value 大于 stackMin 栈顶元素时不弹出 stackMin 栈顶元素,返回value。
public class MyStack1 {
private Stack<Integer> stackData;
private Stack<Integer> stackMin;
public MyStack1(){
this.stackData = new Stack<>();
this.stackMin = new Stack<>();
}
public void push(int newNum){
if(this.stackMin.isEmpty()){
this.stackMin.push(newNum);
}else if(newNum <= this.getMin()){
this.stackMin.push(newNum);
}
this.stackData.push(newNum);
}
public int pop(){
if(this.stackData.isEmpty()){
System.out.println("Your stack is empty!");
}
int value = this.stackData.pop();
if(value == this.getMin()){
this.stackMin.pop();
}
return value;
}
public int getMin(){
if(this.stackMin.isEmpty()){
System.out.println("Your stack is empty!");
}
return this.stackMin.pop();
}
public static void main(String[] args) {
}
}
方法二、
压入数据规则:
假设当前数据为 newNum, 现将其压入 stackData。然后判断 stackMin 是否为空:
- 如果为空:则 newNum 也压入 stackMin 。
- 如果不为空:则比较 newNum 和 stackMin 栈顶元素中哪一个更小:
- 如果 newNum更小或是两者相等,则 newNum 也压入 stackMin;
- 如果 stackMin 中栈顶元素更小,则 stackMin 重复压栈顶元素;
弹出数据规则:
弹出 stackData 元素记作value;弹出 stackMin中栈顶元素;返回 value。
public class MyStack2 {
private Stack<Integer> stackData;
private Stack<Integer> stackMin;
public MyStack2(){
this.stackData = new Stack<Integer>();
this.stackMin = new Stack<Integer>();
}
public void push(int newNum){
if (this.stackMin.isEmpty()){
this.stackMin.push(newNum);
}else if(newNum < this.getMin()){
this.stackMin.push(newNum);
}else{
int newMin = this.stackMin.peek();
this.stackMin.push(newMin);
}
this.stackData.push(newNum);
}
public int pop(){
if(this.stackData.isEmpty()){
System.out.println("Your stack is empty!");
}
this.stackMin.pop();
return this.stackData.pop();
}
public int getMin(){
if(this.stackMin.isEmpty()){
System.out.println("Your stack is empty!");
}
return this.stackMin.pop();
}
public static void main(String[] args) {
}
}
总结:
方法一和方法二其实都是用 stackMin栈保存每一步的最小值。共同点是所有操时间复杂度 O(1)、空间复杂度 O(n)。区别是:方法一 stackMin 压栈节省空间,但是弹栈稍费时间;方案二中 stackMin 压栈稍费空间,但是弹栈时稍省时间。
参考资料:《程序员代码面试指南》左程云 著