实现一个特殊栈,并能返回栈中最小元素
两种数据压入规则,也就是两种实现的方法,利用两个栈,一个stackData栈用来压入所有的数据,所有数据都会压入此栈,一个satckMin用来压入最小元素(对应的就是stackData中的最小元素)。
第一种方法:
(压栈规则):
(1)当将数据压入栈stackData时,判断stackMin栈是否为空,为空则将此数据也压入stackMin栈。
(2)若stackMin栈不为空,则将这个要压入satckData的数据,与stackMin的栈顶元素比较(也就是原来stackMin栈中的最小元素),如果此数据比stackMin的栈顶元素更小或者相等,则将此数据同步压入stackMin栈,成为新的最小元素。反之则不压入。
(出栈规则):
(1)当stackData栈弹出数据时,设此元素为value。然后比较此数据与stackMin的栈顶元素。若相等,则双栈同步弹出元素,若大于,则satckMin栈不弹出栈顶元素。此出栈规则其实与压栈规则是相对应的。同时我们也知道,因为stackMin中栈顶元素只可能是双栈的最小元素,所以不存在在出栈时stackData中数据大于stackMin中的元素的情况。否则说明我们的压栈规则是不合理的,功能并没有实现。
具体实现如下:
第一种方法:
public class GetMinStack {
private Stack<Integer> stackData;//栈数据
private Stack<Integer> stackMin;//放置最小元素的栈
public GetMinStack() {
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);
}
this.stackData.push(newNum);
}
public int pop() {//出栈
if(this.stackData.isEmpty()) {
throw new RuntimeException("your stack is empty");
}
int value = this.stackData.pop();
if(value == this.getMin()){
this.stackMin.pop();
}
return value;
//this.stackMin.pop();
//return this.stackData.pop();
}
private int getMin() {
// TODO Auto-generated method stub
if(this.stackMin.isEmpty()) {
System.out.println("your stack is empty");
}
return this.stackMin.peek();
}
}
第二种方法:
压栈规则与第一种类似:
(1)第一步与上面的第一步相同。
(2)当stackData压入的数据小于或等于stackMin的栈顶元素时,则将此数据也同步压入stackMin。反之则将stackMin中的栈顶元素再重复压入一次stackMin栈。
出栈规则:
(1)与压栈规则相对应,每次都是双栈一起出栈,而不存在比较后stackMin不出栈的情况,因为此种规则下,双栈元素数量相同,同位置的stackMin中的栈顶元素总是双栈中的最小元素。
第二种方法:
public static 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()) {
throw new RuntimeException("Your stack is empty.");
}
this.stackMin.pop();
return this.stackData.pop();
}
public int getMin() {
if (this.stackMin.isEmpty()) {
throw new RuntimeException("Your stack is empty.");
}
return this.stackMin.peek();
}
}
测试代码:
public static void main(String[] args) {
GetMinStack stack1 = new GetMinStack();
stack1.push(3);
System.out.println(stack1.getMin());
stack1.push(4);
System.out.println(stack1.getMin());
stack1.push(2);
System.out.println(stack1.getMin());
stack1.push(5);
System.out.println(stack1.pop());
System.out.println(stack1.getMin());
stack1.push(2);
System.out.println(stack1.getMin());
System.out.println(stack1.pop());
System.out.println(stack1.getMin());
//System.exit(0);
System.out.println("=============");
Mystack2 stack2 = new Mystack2();
stack2.push(3);
System.out.println(stack2.getMin());
stack2.push(4);
System.out.println(stack2.getMin());
stack2.push(1);
System.out.println(stack2.getMin());
System.out.println(stack2.pop());
System.out.println(stack2.getMin());
}
此算法参考了《程序员代码面试指南一书》,说一个小问题,因为第一个方法出栈规则时经过比较后才决定stackMin栈顶元素是否出栈,所以出栈代码与第二种是不同的,参考的代码中,两种出栈代码相同,也就是第一种中出栈方法中注释掉的那段代码是错误的。希望能引起注意。