问题描述
一个栈stack,具有push和pop操作,其时间复杂度皆为O(1)。
设计算法max操作,求栈中的最大值,该操作的时间复杂度也要求为O(1)。
可以修改栈的存储方式,push,pop的操作,但是要保证O(1)的时间复杂度,空间时间复杂度无要求
思路
比较容易想到的是除了原始数据栈之外,再声明一个存放最大值的栈。每次加入数据后,都判断求得最新的最大值,然后把当前的最大值存入到maxStack中。出栈时,除了原始数据pop()之外,对于maxStack中的元素首先要判断原始数据栈中的栈顶元素是否等于maxStack中的栈顶元素,相等的话maxStack也要弹出一个元素,不相等则不用操作maxStack。
这种方式的空间复杂度是O(n),下篇文章会介绍空间复杂度为O(1)的方法。
代码
public class MaxStack {
// 用来存储原始数据
private Stack<Integer> primaryStack = new Stack<Integer>();
// 用来存储最大值,每次加入新元素后都要判断当前元素是否大于上一次加入元素后求得的最大值
private Stack<Integer> maxStack = new Stack<Integer>();
//private int maxValue;
public void push(int num) {
primaryStack.push(num);
if(maxStack.isEmpty()) {
maxStack.push(num);
}else{
int maxValue = maxStack.peek();
// 这里的判断对于空间占用有个问题
// 即可能会重复存储相同的最大值
// 举个例子 ,当输入元素为1 2 5 5 5
// maxStack中存储的1 2 5 5 5
// 为了避免重复存储,节省空间,则需要对重复的情况进行标记
if(num>=maxValue){
maxStack.push(num);
}
}
}
public int pop(){
// 原始数据栈为空,则无法出栈,
if(primaryStack.isEmpty()) {
// 这里使用了Stack类中peek元素时,如果为空抛出的异常
// 也可以return一个数,用于标识为空情况
throw new EmptyStackException();
}
int maxValue = primaryStack.peek();
if(maxValue == maxStack.peek()) {
maxStack.pop();
}
return primaryStack.pop();
}
public int getMaxValue(){
return maxStack.peek();
}
}