题目:
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.
题意:
设计一个支持push、pop、top和在常数时间内返回最小元素的getMin()函数。
1、push(x)--将x压入栈;
2、pop()--移除一个栈顶元素;
3、top()--得到栈顶元素;
4、getMin()--检索返回堆栈中最小的元素;
思路一:
最小栈与原来的栈相比只是多了一个getMin(),可以返回该栈的最小值。解题方案为,使用两个栈来实现,一个栈按顺序存储push进来的数据,另一个用来存出现过得最小值。
代码:C++版:68ms
class MinStack { public: /** initialize your data structure here. */ MinStack() { } void push(int x) { _stack.push(x); if (_minStack.empty() || x <= _minStack.top()) _minStack.push(x); } void pop() { if (!_stack.empty()) { if (_stack.top() == _minStack.top()) _minStack.pop(); _stack.pop(); } } int top() { if (!_stack.empty()) return _stack.top(); return 0; } int getMin() { if (!_minStack.empty()) return _minStack.top(); return 0; } private: stack<int> _stack; stack<int> _minStack; }; /** * Your MinStack object will be instantiated and called as such: * MinStack obj = new MinStack(); * obj.push(x); * obj.pop(); * int param_3 = obj.top(); * int param_4 = obj.getMin(); */
代码:java版:150ms
public class MinStack { ArrayList<Integer> stack = new ArrayList<Integer>(); ArrayList<Integer> minStack = new ArrayList<Integer>(); public void push(int x) { stack.add(x); if (minStack.isEmpty() || minStack.get(minStack.size()-1) >= x) minStack.add(x); } public void pop() { if (stack.isEmpty()) return ; int elem = stack.remove(stack.size()-1); if (!minStack.isEmpty() && elem == minStack.get(minStack.size()-1)) minStack.remove(minStack.size()-1); } public int top() { if (!stack.isEmpty()) return stack.get(stack.size()-1); return 0; } public int getMin() { if (!minStack.isEmpty()) return minStack.get(minStack.size()-1); return 0; } } /** * Your MinStack object will be instantiated and called as such: * MinStack obj = new MinStack(); * obj.push(x); * obj.pop(); * int param_3 = obj.top(); * int param_4 = obj.getMin(); */
思路二:
利用一个栈存储最小值与当前值之间的差值,每次根据压入堆栈值得大小决定是否更新最小值,如果比最小值更小则更新最小值。pop操作时,如果弹出的栈值为负数,则需要更新最小值到其上一个最小值状态,即执行min = min - pop操作。
代码:java版:122ms
public class MinStack { long min; Stack<Long> stack; /** initialize your data structure here. */ public MinStack() { stack = new Stack<Long>(); } public void push(int x) { if (stack.isEmpty()) { stack.push(0L); min = x; } else { stack.push(x-min); //如果x-min为负值,则需要改变最小值 if (x < min) min = x; } } public void pop() { if (stack.isEmpty()) return ; long pop = stack.pop(); if (pop < 0) min = min - pop; //如果pop为负值,需要将min值更新到其上一次状态 } public int top() { long top = stack.peek(); if (top > 0) { return (int)(top + min); } else { return (int)(min); } } public int getMin() { return (int)min; } } /** * Your MinStack object will be instantiated and called as such: * MinStack obj = new MinStack(); * obj.push(x); * obj.pop(); * int param_3 = obj.top(); * int param_4 = obj.getMin(); */
思路三:
基于java的内部类用来存储当前值与最小值。维护一个Element对象的栈即可,当需要压入一个数时,基于该数构造一个Element对象用来存储当前的value值与min最小值。其本质相当于将思路一种的两个堆栈利用内部类转换为同一个堆栈实现。
代码:java版:141ms
public class MinStack { static class Element { //内部类Element数据结构 final int value; final int min; Element (final int value, final int min) { //内部类构造函数 this.value = value; this.min = min; } } final Stack<Element> stack = new Stack<Element>(); //初始化Element栈 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; } } /** * Your MinStack object will be instantiated and called as such: * MinStack obj = new MinStack(); * obj.push(x); * obj.pop(); * int param_3 = obj.top(); * int param_4 = obj.getMin(); */