【题目】实现一个特殊的栈,在实现栈的基本功能的基础上,再实现返回栈中最小元素的操作。
【要求】
1. pop、push、getMin功能时间复杂度为O(1)。
【设计方案】
1. 采用双栈的方式来实现
2. 将新元素newNum压入到栈stackData后,对栈stackMin判空。如果为空直接压入元素,不为空则弹出元素比较大小,压入更小的那个元素。
3. 弹出数据时,首先对栈stackMin判空,栈空抛异常,非空栈stackMin和栈stackData抛出数据。
【代码实现】
import java.util.Stack;
/**
* @program: Java
* @description: 设计一个有getMin功能的栈
* @author: lzp
* @create: 2018/4/30
*/
public class GetMinStack {
private Stack<Integer> stackData; // 保存当前栈中元素
private Stack<Integer> stackMin; // 保存栈中元素的最小值
/**
* 实例化两个栈
*/
public GetMinStack() {
this.stackData = new Stack<>();
this.stackMin = new Stack<>();
}
/**
* 栈元素压入
*
* @param newNum
*/
public void push(Integer newNum) {
if (this.stackMin.isEmpty()) { // stackMin为空,直接压入
this.stackMin.push(newNum);
} else if (newNum < this.getMin()) { // newNum为当前最小值
this.stackMin.push(newNum);
} else { // 不是最小,压入上一个值
this.stackMin.push(this.getMin());
}
this.stackData.push(newNum);
}
/**
* 栈元素弹出
*
* @return
*/
public int pop() {
if (this.stackData.isEmpty()) {
throw new RuntimeException("栈空!");
}
this.stackMin.pop();
return this.stackData.pop();
}
/**
* 判空并获取栈顶元素
*
* @return
*/
public int getMin() {
if (this.stackMin.isEmpty()) {
throw new RuntimeException("栈空!");
}
return this.stackMin.peek();
}
public static void main(String[] args) {
GetMinStack stack = new GetMinStack();
stack.push(5);
stack.push(2);
stack.push(4);
System.out.println(stack.getMin());
stack.pop();
System.out.println(stack.getMin());
}
}
【另一种设计方案】
1. 压入新元素newNum时,栈stackData压入元素,栈stackMin空直接压入元素;不为空,则比较newNum与栈顶元素大小,newNum大于栈顶元素,不压入;小于等于等于栈顶元素,则压入。
2. 弹出策略:弹出时,栈stackData判空,栈空抛异常。非空,则比较栈顶元素与栈stackMin栈顶元素值的大小,如果相等,栈stackMin弹出栈顶元素。
【代码实现】
import java.util.Stack;
/**
* @program: Java
* @description: 设计一个有getMin功能的栈
* @author: lzp
* @create: 2018/5/1
*/
public class GetMinStack2 {
private Stack<Integer> stackData;
private Stack<Integer> stackMin;
public GetMinStack2() {
stackData = new Stack<>();
stackMin = new Stack<>();
}
public void push(Integer 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("栈空!");
}
int topNum = this.stackData.pop();
if (topNum == this.getMin()) {
this.stackMin.pop();
}
return topNum;
}
public int getMin(){
if(this.stackMin.isEmpty()){
throw new RuntimeException("栈空!");
}
return this.stackMin.peek();
}
}
【设计方案比较】
相同点:两种方案的所有操作的时间复杂度都是O(1),空间复杂度都是O(n)。
不同点:方案1,压入元素省时间,弹出元素费时间;方案2,压入元素费时间,弹出元素省时间。