3.2问题:
请设计一个栈,除去pop与push方法,还支持min方法,可返回栈元素中的最小值。push、pop和min三个方法的时间复杂度必须为O(1)。
思考:
一种解法是,在Stack类里添加一个int型的minvalue。当minvalue出栈时,我们会搜索整个栈,找出新的最小值。可惜,这不符合入栈出栈时间复杂度O(1)的要求。另一种解法,就是每次入栈都要记下这个状态下的最小值。
import java.util.*;
class StackMin{
public static void main(String args[]){
StackWithMin a = new StackWithMin();
a.push(6);
System.out.println(a.min());
a.push(5);
System.out.println(a.min());
a.push(4);
System.out.println(a.min());
a.push(3);
System.out.println(a.min());
a.push(2);
System.out.println(a.min());
a.push(1);
System.out.println(a.min());
a.push(2);
System.out.println(a.min());
a.push(3);
System.out.println(a.min());
}
}
class StackWithMin extends Stack<NodeWithMin> {
public void push(int value){
int newMin = Math.min(value,min());
super.push(new NodeWithMin(value,newMin));
}
public int min(){
if(this.isEmpty()){
return Integer.MAX_VALUE;//如果为空的话,返回极限大值。
}else{
return peek().min; //返回栈顶元素的绑定的最小值。
}
}
}
class NodeWithMin{
public int value;
public int min;
public NodeWithMin(int v,int min){
value = v;
this.min=min;
}
}
以上做法有个缺点,当栈很大的时候,每个元素都要记录min,就会浪费大量的空间。
下面一个方法可以节省空间:
import java.util.*;
class StackMin{
public static void main(String args[]){
StackWithMin a = new StackWithMin();
a.push(6);
System.out.println(a.min());
a.push(5);
System.out.println(a.min());
a.push(4);
System.out.println(a.min());
a.push(3);
System.out.println(a.min());
a.push(2);
System.out.println(a.min());
a.push(1);
System.out.println(a.min());
a.push(2);
System.out.println(a.min());
a.push(3);
System.out.println(a.min());
System.out.println("开始你的表演:");
a.pop();
System.out.println(a.min());
a.pop();
System.out.println(a.min());
a.pop();
System.out.println(a.min());
a.pop();
System.out.println(a.min());
a.pop();
System.out.println(a.min());
}
}
class StackWithMin extends Stack<Integer> {
Stack<Integer> s2;
public StackWithMin(){
s2 = new Stack<Integer>();
}
public void push(int value){
if(value<=min()){
s2.push(value);
}
super.push(value);
}
public Integer pop(){
int value =super.pop();
if(value==min()){//如果弹出的值是当前最小值,则s2也弹出一个值。s2的栈底到栈顶必定是数字从大到小排列
s2.pop();
}
return value;
}
public int min(){
if(s2.isEmpty()){
return Integer.MAX_VALUE;//如果为空的话,返回极限大值。
}else{
return s2.peek(); //返回栈顶元素的绑定的最小值。
}
}
}