最小栈
题目需求:
实现一个这样的栈,这个栈除了可以进行普通的push、pop操作以外,还可以进行getMin的操作,getMin方法被调用后,会返回当前栈的最小值。栈里面存放的都是 int 整数,
力扣题目:实现一个最小栈
暴力版本实现
时间复杂度为O(n);空间复杂度为O(1)
采用一个指针来指向最小元素下标,每次出栈都要判断出栈元素是否是当前最小,如果是就要去遍历,更新最小指针,
class MinStack {
int[] nums;
int minIndex;
int index;
/** initialize your data structure here. */
public MinStack() {
this.nums=new int[20000];
this.index=0;
this.minIndex=-1;
}
public void push(int x) {
nums[index]=x;
index++;
if(minIndex==-1){
minIndex=0;
}else if(x<nums[minIndex]){
minIndex=index-1;
}
}
public void pop() {
index--;
if(index==minIndex){
minIndex=0;
for(int i=0;i<index;i++){
if(nums[i]<=nums[minIndex]){
minIndex=i;
}
}
}
}
public int top() {
return nums[index-1];
}
public int min() {
return nums[minIndex];
}
}
辅助栈实现
采用一个辅助栈来实现,其时间复杂度为O(1),空间复杂度为O(n)
有两个栈 s1和 s2,s1 是目标栈,s2 是辅助栈,用来存放最小值。
- 每次 getMin 的时候,直接从 s2 栈顶获取即可
- 每次入栈,s1直接入栈,s2则需要判断,若当前入栈元素小于s2的栈顶元素,则直接入栈,若当前元素大于等于s2的栈顶元素,则把s2的栈顶元素值,入栈一次。
- 每次出栈,s1,s2都直接弹出即可
- 需要注意,若首次入栈,也可以当s2为空栈的时候,直接将当前元素入栈
class MinStack {
Stack<Integer> s1;
Stack<Integer> s2;
/** initialize your data structure here. */
public MinStack() {
this.s1=new Stack<Integer>();
this.s2=new Stack<Integer>();
}
public void push(int x) {
s1.push(x);
if(s2.empty()){
s2.push(x);
}else{
if(x<s2.peek()){
s2.push(x);
}else{
s2.push(s2.peek());
}
}
}
public void pop() {
s1.pop();
s2.pop();
}
public int top() {
return s1.peek();
}
public int min() {
return s2.peek();
}
}
使用存差值实现(最优)
public class MinStack {
private Stack<Integer> stack = new Stack<Integer>();
private int min;
public void push(int x) {
if (stack.isEmpty()) {
min = x;
stack.push(0);
} else {
// 计算差值
int compare = x - min;
stack.push(compare);
// 如果差值小于0,显然 x 成为最小值,否则最小值不变
min = compare < 0 ? x : min;
}
}
public void pop() {
int top = stack.peek();
// 如果top小于0,显然最小值也一并会被删除,此时更新最小值
min = top < 0 ? (min - top) : min;
stack.pop();
}
public int getMin() {
return min;
}
}