Design a stack that supports push, pop, top, and retrieving the minimum element in constant time.
push(x) -- Push element x onto stack.
pop() -- Removes the element on top of the stack.
top() -- Get the top element.
getMin() -- Retrieve the minimum element in the stack.
Example:
MinStack minStack = new MinStack();
minStack.push(-2);
minStack.push(0);
minStack.push(-3);
minStack.getMin(); --> Returns -3.
minStack.pop();
minStack.top(); --> Returns 0.
minStack.getMin(); --> Returns -2.
Solution1(recommended):Two Stack(element and max)
思路: build two stacks,stack1 for elements, and stack2 for min_value. Stack1和Stack2可以完全同步push pop,即每个元素都物理上对应有一个到它时候的min. Like Solution1a
也可以省一下空间,因为当一个元素e比前面的min大的时候,then e can
never be the min, so we do not need to record it. SO we only record the elements which have chances to be the min, pop元素的时候,==min的元素才也pop min,不等于的时候(说明小于),没贡献,只pop元素。Note:这样的minstack是单调递减的
Like Solution1b
Max同理,
Time Complexity: O(N) Space Complexity: O(2N)
Solution2:One Stack(存gap between min and current value)
思路: min只用一个变量保存,stack中存的是the gap between the min value and the current value。pop时:当gap值小于0是,说明current value更小,此时min有变化,所以pop时候需要将min修正过来,其他直接pop。
Note:因为有+-计算,所以为避免MAX_VALUE - Integer.MIN_VALUE出界情况,采用long,所以space其实和solution1一样大
Time Complexity: O(N) Space Complexity: O(2N)
Solution1a Code:
class MinStack {
class Element {
int value;
int min;
Element(int value, int min) {
this.value = value;
this.min = min;
}
}
final Deque<Element> stack = new ArrayDeque<>();
public void push(int x) {
final int min = (stack.empty()) ? x : Math.min(stack.peek().min, x);
stack.push(new Element(x, min));
}
public void pop() {
stack.pop();
}
public int top() {
return stack.peek().value;
}
public int getMin() {
return stack.peek().min;
}
}
Solution1b Code:
class MinStack {
private Deque<Integer> mStack = new ArrayDeque<Integer>();
private Deque<Integer> mMinStack = new ArrayDeque<Integer>();
public void push(int x) {
mStack.push(x);
if (mMinStack.size() != 0) {
int min = mMinStack.peek();
if (x <= min) {
mMinStack.push(x);
}
} else {
mMinStack.push(x);
}
}
public void pop() {
int x = mStack.pop();
if (mMinStack.size() != 0) {
if (x == mMinStack.peek()) {
mMinStack.pop();
}
}
}
public int top() {
return mStack.peek();
}
public int getMin() {
return mMinStack.peek();
}
}
Solution2 Code:
public class MinStack {
long min;
Stack<Long> stack;
public MinStack(){
stack=new Stack<>();
}
public void push(int x) {
if (stack.isEmpty()){
stack.push(0L);
min=x;
}else{
stack.push(x-min);//Could be negative if min value needs to change
if (x<min) min=x;
}
}
public void pop() {
if (stack.isEmpty()) return;
long pop=stack.pop();
if (pop<0) min=min-pop;//If negative, increase the min value
}
public int top() {
long top=stack.peek();
if (top>0){
return (int)(top+min);
}else{
return (int)(min);
}
}
public int getMin() {
return (int)min;
}
}