两种方式实现,第一种用空间换时间,第二种用时间换空间
空间换时间
基本思想
- 用两个栈来实现,一个栈维护入栈数据(数据栈),一个栈维护最小值(最小栈)
- 元素入栈时,比较入栈元素与最小栈栈顶
- 如果最小栈栈顶元素更小,那么再次将该最小栈栈顶元素压入最小栈
- 如果入栈元素更小,那么将入栈的元素同步压入最小栈
- 元素出栈时,数据栈与最小栈同步出栈即可,最小栈弹出元素即为当前栈中最小值
代码
import java.util.Stack;
/**
* 实现栈,并且可以获取栈中的最小值
*
* 解决:两个栈 -> 栈1维护所有数据,栈2维护最小值
*/
public class MinStack {
public static class MyStack{
//初始化定义两个栈
public Stack<Integer> dataStack;
public Stack<Integer> minStack;
public MyStack(){
dataStack = new Stack<>();
minStack = new Stack<>();
}
//入栈
public void push(int value){
//判断最小栈的处理
//若最小栈为空或最小栈栈顶值大于传入值,则放入
if (minStack.isEmpty() || minStack.peek() > value){
minStack.push(value);
} else {
//否则,再次在最小栈放入最小栈栈顶元素
minStack.push(minStack.peek());
}
//数据栈放入值
dataStack.push(value);
}
//出栈
public int pop(){
//判空
if (dataStack.isEmpty()){
System.out.println("栈空");
return -1;
}
//弹出最小栈栈顶,返回数据栈栈顶
minStack.pop();
System.out.println(dataStack.peek());
return dataStack.pop();
}
public int getMin(){
return minStack.peek();
}
}
public static void main(String[] args) {
MyStack myStack = new MyStack();
myStack.push(5);
System.out.println(myStack.getMin()); // 5 5
myStack.push(2);
System.out.println(myStack.getMin()); // 2 2
myStack.push(3);
System.out.println(myStack.getMin()); // 3 2
myStack.push(1);
System.out.println(myStack.getMin()); // 1 1
myStack.pop();
System.out.println(myStack.getMin()); // 3 2
}
}
复杂度分析
所谓空间换时间,
就是元素每次进栈时,最小栈同步会压入,占用了和数据栈同等大小的空间
但获取栈中的最小值时,只需要获取最小栈栈顶元素即可,节省了时间
时间换空间
基本思想
- 同样定义数据栈和最小栈
- 元素入栈时,比较入栈元素与最小栈栈顶
- 如果入栈元素>最小栈栈顶元素,则最小栈不压入
- 如果入栈元素<=最小栈栈顶元素,则最小栈同步压入
- 元素出栈时
- 只有数据栈栈顶元素与最小栈栈顶元素相等时,才会同步弹出
- 这样才可以保证最小栈栈顶元素始终为栈的最小值
代码
import java.util.Stack;
/**
* 实现栈,并且可以获取栈中的最小值
*
* 解决:两个栈 -> 栈1维护所有数据,栈2维护最小值
* 入栈时:栈2只有在其栈顶元素≤当前值时才入栈
* 出栈时:栈2只有栈顶元素 = 数据栈栈顶元素时才出栈
*/
public class MinStack2 {
public static class MyStack{
//初始化定义两个栈
public Stack<Integer> dataStack;
public Stack<Integer> minStack;
public MyStack(){
dataStack = new Stack<>();
minStack = new Stack<>();
}
//入栈
public void push(int value){
//判断最小栈的处理
//若最小栈为空或传入值≤最小栈栈顶值,则放入
if (minStack.isEmpty() || value <= minStack.peek()){
minStack.push(value);
}
//数据栈放入值
dataStack.push(value);
}
//出栈
public int pop(){
//判空
if (dataStack.isEmpty()){
System.out.println("栈空");
return -1;
}
//若数据栈栈顶=最小栈栈顶,弹出最小栈栈顶,返回数据栈栈顶
if (dataStack.peek() == minStack.peek()){
minStack.pop();
}
System.out.println(dataStack.peek());
return dataStack.pop();
}
public int getMin(){
return minStack.peek();
}
}
public static void main(String[] args) {
MyStack myStack = new MyStack();
myStack.push(5);
System.out.println(myStack.getMin()); // 5 5
myStack.push(2);
System.out.println(myStack.getMin()); // 2 2
myStack.push(3);
System.out.println(myStack.getMin()); // 3 2
myStack.push(1);
System.out.println(myStack.getMin()); // 1 1
myStack.pop();
System.out.println(myStack.getMin()); // 3 2
}
}
复杂度分析
所谓时间换空间,
就是元素每次进栈时,最小栈不会同步会压入,只有<=最小栈栈顶元素时才会压入,最小栈占用空间会小
但获取栈中的最小值时,需要判断数据栈栈顶元素与最小栈栈顶元素是否相等,相等时才会弹出,因为增加了逻辑判断,所以会比方法一占用更多的时间