思路与分析:
在遇到问题之前,我们先来思考一个问题,如果题目仅仅是问:给你一个数据栈,要你编码实现去查找栈中最小的元素。那么你要如何实现?这个问题很简单,我们马上就能把代码写出来:
package cn.csu;
import java.util.Stack;
import java.util.Iterator;
public class StackFindMin {
public int min(Stack<Integer> stack){
int min = stack.peek();
Iterator iterator = stack.iterator();
while (iterator.hasNext()){
int value = (int)iterator.next();
if(value<=min){
min =value;
}
}
return min;
}
}
上述代码就实现了对给定栈最小元素的查找。但是,在上述代码的min方法中,通过时间复杂度分析,min方法的时间复杂度为O(n),显然不符合这个题要考察的内容。
那么如何才能实现在时间复杂度为O(1)的方法中实现查找最小数呢?
思路:我们借助一个辅助栈,给定栈我们成为数据栈。当有元素入栈时,我们比较入栈元素与原最小元素的大小,如果入栈元素比原最小元素大,那么把该元素入数据栈,把原最小元素入辅助栈。如果入栈元素比原最小元素小,那么把该元素分别入数据栈和辅助栈。这样就保证了辅助栈的栈顶一直都是最小元素。
我们来看看具体代码实现:
package cn.csu;
import java.util.Stack;
public class StackMin<T extends Comparable<T>> {
//数据栈
private Stack<T> dataStack;
//辅助栈
private Stack<Integer> supStack;
public StackMin(){
this.dataStack = new Stack<>();
this.supStack = new Stack<>();
}
public T pop(){
if(dataStack.isEmpty()){
throw new RuntimeException("数据栈是空的");
}
//这里说明一下,如果有数据,那么按照我们的思路可以知道,辅助栈和数据栈的元素个数是相等的
//这里我们让两个栈都进行出栈操作
supStack.pop();
return dataStack.pop();
}
/**
* 入栈操作
* @param t
*/
public void push(T t){
//如果入栈元素为空,则跑出异常
if(t== null) {
throw new RuntimeException("入栈元素不能为空!");
}
if(dataStack.isEmpty()){//如果数据栈是空的,将元素入栈,同时更新最小栈中的数据
dataStack.push(t);
supStack.push(0);
}else{
//获取数据栈中最小的元素(入栈之前的最小元素)
T e = dataStack.get(supStack.peek());
//将t入栈
dataStack.push(t);
//比较t和e
if(t.compareTo(e)<0){//如果t比e小,将t所在的位置(下标)入辅助栈
supStack.push(dataStack.size()-1);
}else{
// 插入的元素不比原来的最小元素小,复制最小栈栈顶元素,将其入栈
supStack.push(supStack.peek());
}
}
}
public T min(){
//如果辅助栈为空,则说明数据栈也为空,则跑出异常
if(supStack.isEmpty()){
throw new RuntimeException("栈中没有元素!");
}
return dataStack.get(supStack.peek());
}
public static void main(String[] args) {
StackMin<Integer> stack = new StackMin<>();
stack.push(3);
System.out.println(stack.min() == 3);
stack.push(4);
System.out.println(stack.min() == 3);
stack.push(2);
System.out.println(stack.min() == 2);
stack.push(3);
System.out.println(stack.min() == 2);
stack.pop();
System.out.println(stack.min() == 2);
stack.pop();
System.out.println(stack.min() == 3);
stack.push(0);
System.out.println(stack.min() == 0);
}
}