题目:
题目解读:
题目很明显是要我们返回栈中最小的元素,一边在压栈的同时要知道栈中最小的元素是谁,在出栈的时候也要知道最小的元素是谁。
方法一:辅助栈
一个栈定义普通的进出,一个栈存储都是当前插入的元素与栈中最小元素的比较(当前插入的值都是当前值中最小的元素)这个就比较好理解了没啥好讲的,时间复杂度为O(1),两个栈空间复杂度都是O(n)。
class MinStack {
Deque<Integer> xStack;//普通栈
Deque<Integer> minStack;//最小栈
public MinStack() {
xStack = new LinkedList<Integer>();
minStack = new LinkedList<Integer>();
//minStack.push(Integer.MAX_VALUE);
}
public void push(int val) {
xStack.push(val);
if(minStack.size()==0){//当最小栈没有元素则直接插入
minStack.push(val);
}else{
minStack.push(Math.min(minStack.peek(),val));
}
}
public void pop() {
xStack.pop();
minStack.pop();
}
public int top() {
return xStack.peek();
}
public int getMin() {
return minStack.peek();
}
}
方法二:利用差值
我在做这题的时候一下子就用方法一写出来了,但是在看题解的时候,看到有人说在面试的时候面试官要求不能用额外空间来辅助,我就左思右想那是不是可以储存一个栈中最小值和栈里面都是当前插入数与最小数的差值来进行管理。思路一出,马上敲!
我们先定义一个栈中最小值变量min,栈用Java中的集合实现Deque<Long> s = new LinkedList( );
Stack<Long> stack;
long min;
public MinStack() {
stack = new Stack<>();
}
首先是push操作: 因为是插入操作,我们得知道更新之后的栈内最小值,如果当前栈中没有元素,当插入第一个元素,比如5时,栈内最小值没有就为0,那么插入0,最小值为5,记得更新最小值,先懂这个操作,不明白也没事,看下去就懂了。
//将当前值与当前最小值的差值压入栈中 public void push(int val) { if(stack.isEmpty()) { stack.push(0L); min = val; } else { //一定要先压栈再更新最小值 stack.push((long)(val - min)); min = Math.min(min, val); } }
接下来是pop( ) 弹出操作,我们要记得在弹出的时候更新最小值,这里有一个小细节,如果当前值与最小值的差值为负数的话,是不是意味着当前值小于最小值,这里我们可以用一个式子来进行演示:
当栈顶元素为-4时,当前栈中实际最小值为1,第二小值为5,我们倒过来推,当要插入1这个数时,栈中应该存储的值是当前值减去最小值,也就是1-5 = -4。那么当要弹出栈顶元素而且为负数时,我们就应该更新最小值,将第二小的值作为最小值,也就是以前的最小值减去当前栈顶元素就是最小值 1-(-4)= 5,如果栈顶元素为正数,代表他实际的值比最小值大,因此不用更新最小元素。
public void pop() {
long pop = stack.pop();
//如果值小于0,说明我们把最小值弹出去了,需要更新最小值
if(pop < 0) {
min = min - pop;
}
}
接下来是查看栈顶元素top( ),我们就想因为栈中存储的是当前值与最小值的差值,我们查看栈顶元素得知道实际元素是什么,如果当栈顶元素是负数的时候,证明当前值比最下值还要小,最小值更新为当前值,因此当最小值为负数,当前值为最小值。当栈顶元素为正数时,表示当前值比最小值要大,栈顶元素存储时当前值减去最小值的差值,因此,实际值就为差值加上最小值。
public int top() {
//如果栈顶元素小于0,说明栈顶元素就是当前最小值
if(stack.peek() < 0) {
return (int)min;
} else {
return (int)(stack.peek()+min);
}
}
最后就是返回最小元素,直接返回min就好了
public int getMin() {
return (int)min;
}
全部代码
class MinStack {
Stack<Long> stack;
long min;
public MinStack() {
stack = new Stack<>();
}
//将当前值与当前最小值的差值压入栈中
public void push(int val) {
if(stack.isEmpty()) {
stack.push(0L);
min = val;
} else {
//一定要先压栈再更新最小值
stack.push((long)(val - min));
min = Math.min(min, val);
}
}
public void pop() {
long pop = stack.pop();
//如果值小于0,说明我们把最小值弹出去了,需要更新最小值
if(pop < 0) {
min = min - pop;
}
}
public int top() {
//如果栈顶元素小于0,说明栈顶元素就是当前最小值
if(stack.peek() < 0) {
return (int)min;
} else {
return (int)(stack.peek()+min);
}
}
public int getMin() {
return (int)min;
}
}