Description
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.
Solution 1(C++)
class MinStack {
stack<int> s;
public:
/** initialize your data structure here. */
MinStack() {
}
void push(int x) {
s.push(x);
}
void pop() {
s.pop();
}
int top() {
return s.top();
}
int getMin() {
stack<int> ss;
int Min=INT_MAX;
while(!s.empty()){
ss.push(s.top());
Min=min(Min, s.top());
s.pop();
}
while(!ss.empty()){
s.push(ss.top());
ss.pop();
}
return 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();
*/
Solution 2(C++)
static int x = []() { std::ios::sync_with_stdio(false); cin.tie(NULL); return 0; }();
class MinStack {
long long min;
stack<long long>l;
public:
MinStack() {
min = INT_MIN;
}
void push(int x) {
if (l.empty()) {
l.push(0); min = x;
} else {
l.push(x - min);
if (x < min) {
min = x;
}
}
};
void pop() {
if (!l.empty()) {
long long t = l.top(); l.pop();
if (t < 0) {
min -= t;
}
}
};
int top() const {
if (l.empty()) {
return INT_MIN;
}
long long t = l.top();
return (int) (t < 0 ? min : min + t); };
int getMin() const {
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();
*/
Solution 3(C++)
class MinStack {
private:
stack<int> s1;
stack<int> s2; //s2用来存放较小值,插入者若小于s2的栈顶,则放入作为新的最小值处理;
public:
void push(int x) {
s1.push(x);
if (s2.empty() || x <= getMin()) s2.push(x);
}
void pop() {
if (s1.top() == getMin()) s2.pop();
s1.pop();
}
int top() {
return s1.top();
}
int getMin() {
return s2.top();
}
};
/**
* 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()函数中,删除s1的栈顶,如果s1的栈顶也是s2的栈顶,那么s2的栈顶也会删除掉,其实就是s1的栈顶是目前的最小值,那么s2也要更新。但是s1的栈顶不是最小值的话,那么s2不用更新。
我当时就觉得有问题啊,因为,pop()函数执行多次,s1的栈顶不是最小值,但是s2的次小值,举个例子:s1:(4,3,1,2),对应s2:(4,3,2,1)。那么我删除s1的栈顶2,s2不更新,再删除s1的栈顶1,s2也删除栈顶,这时,s2 的栈顶就是2了,但是2已经在第一次s1的pop操作中,就删除了。
后来,仔细一想,你就会发现我这个漏洞根本就不会出现,因为,这与栈的特性有关。其实s2根本就不是(4,3,2,1)。重新回顾一下push()函数中的算法,就会发现,其实2根本没有插入s2中,s2其实是(4,3,1)。因为在s1push1之后,s2的栈顶就是1,这时s1push 2,s2栈顶是1,2 > 1,那么2不会插入s2。
所以解法三是可行的。
程序分析
程序分析的部分着重分析一下解法二,一开始就是用了lamda表达式,可以参考: C++—— Lambda表达式。
大概能明白解法二的意思,这个stack储存的不是输入的值,而是处理过的,储存的是与最小值相差的值。但是要注意这个结构中会有负数,因为最小值的更新是在push之后完成的。
但是为什么要在开头加这样一句话,我还是不太明白的。目前有关这句话找到的资料是:ios::sync_with_stdio(false);。
虽然不太明白个别几句,但是这种想法还是值得学习的,那就是不要被禁锢住,只要满足输入与输出就可以了。不是说stack里都要储存要属于的值,可以在中间加一个映射,也许会帮助解决很多问题。