- Min Stack
Implement a stack with min() function, which will return the smallest number in the stack.
It should support push, pop and min operation all in O(1) cost.
Example
push(1)
pop() // return 1
push(2)
push(3)
min() // return 2
push(1)
min() // return 1
Notice
min operation will never be called if there is no number in the stack.
代码如下:
注意:
- pop()完之后要注意stack为空的情况。如果为空,重新将min_num设为INT_MAX;
- 如果pop()掉了min_num,要注意stack中是否还有多余的min_num。所以这里必须用map来记录每个数出现频数。
class MinStack {
public:
MinStack() : min_num(INT_MAX) {
// do intialization if necessary
}
/*
* @param number: An integer
* @return: nothing
*/
void push(int number) {
s.push(number);
if (number < min_num) {
min_num = number;
mp[number] = 1;
} else if (number == min_num) {
mp[number]++;
}
}
/*
* @return: An integer
*/
int pop() {
if (!s.empty()) {
int topNum = s.top();
s.pop();
if (topNum == min_num) {
if (mp[topNum] == 1) {
mp.erase(topNum);
if (!mp.empty())
min_num = mp.begin()->first;
else
min_num = INT_MAX;
} else {
mp[topNum]--;
}
}
return topNum;
}
}
/*
* @return: An integer
*/
int min() {
return min_num;
}
private:
stack<int> s;
int min_num;
unordered_map<int, int> mp; //num, freq
};
二刷:
class MinStack {
public:
MinStack() {
minElem = INT_MAX;
}
/*
* @param number: An integer
* @return: nothing
*/
void push(int number) {
s.push(number);
if (mp.find(number) == mp.end()) {
mp[number] = 1;
} else {
mp[number]++;
}
minElem = std::min(minElem, number);
}
/*
* @return: An integer
*/
int pop() {
if (!s.empty()) {
int topElem = s.top();
s.pop();
if (mp[topElem] == 1) {
mp.erase(topElem);
if (mp.empty()) {
minElem = INT_MAX;
} else {
minElem = mp.begin()->first;
}
} else {
mp[topElem]--;
}
return topElem;
}
}
/*
* @return: An integer
*/
int min() {
return minElem;
}
private:
stack<int> s;
map<int, int> mp; //number, count
int minElem;
};
上面用到了map,似乎应该改为unordered_map才满足O(1)的时间复杂度
解法3:用两个栈。其中minStk的top保存对应到dataStk的top的最小值。
class MinStack {
public:
MinStack() {
// do intialization if necessary
}
/*
* @param number: An integer
* @return: nothing
*/
void push(int number) {
dataStk.push(number);
if (number < minV) minV = number;
minStk.push(minV);
}
/*
* @return: An integer
*/
int pop() {
int dataStkTop = dataStk.top();
int minStkTop = minStk.top();
dataStk.pop();
minStk.pop();
if (minStk.empty()) {
minV = INT_MAX;
} else if (minV == minStkTop) { //important fix
minV = minStk.top(); //!!!
}
return dataStkTop;
}
/*
* @return: An integer
*/
int min() {
return minStk.top();
}
private:
stack<int> dataStk;
stack<int> minStk;
int minV = INT_MAX;
};
注意下面的fix很重要
else if (minV == minStkTop) { //important fix
minV = minStk.top(); //!!!
}
注意当minStk执行pop()之后,因为minStk之前的top可能就是minV,所以minV会不准,这是我们要把minV更新到minStk的现在的top。
一个例子是
push(24)
min()
push(20)
min()
pop()
min()
push(24)
min()
具体执行流程
dataStk push 24 minStak push 24
minStk.top() = 24
dataStk push 20 minStak push 20
minStk.top() = 20
dataStk pop 20 minV = 20
minStk.top() = 24
dataStk push 24 minStak push 20
minStk.top() = 20
输出结果:
Output Data
[24,20,20,24,20]
Expected
[24,20,20,24,24]
即最后一个pop()操作后,minV还是20,应该调整到minStk.top(),也就是24才对。
又改进了一下,minStk并不需要每次都跟dataStk一样同步push和pop,只有当dataStk要push的元素<=minV时,我们才push它到minStk。也只有当pop出来的元素刚好跟当前的minV相等时,我们才pop minStk,并相应调整minV。这样minStk的大小可以相对小一些。
class MinStack {
public:
MinStack() {
// do intialization if necessary
}
/*
* @param number: An integer
* @return: nothing
*/
void push(int number) {
dataStk.push(number);
if (number <= minV) {
minV = number;
minStk.push(minV);
}
}
/*
* @return: An integer
*/
int pop() {
int dataStkTop = dataStk.top();
int minStkTop = minStk.top();
dataStk.pop();
if (minV == dataStkTop) {
minStk.pop();
if (minStk.empty()) minV = INT_MAX;
else minV = minStk.top();
}
return dataStkTop;
}
/*
* @return: An integer
*/
int min() {
return minStk.top();
}
private:
stack<int> dataStk;
stack<int> minStk;
int minV = INT_MAX;
};
又优化了一下,根本就没有必要维护minV,因为minStk.top()就是minV。注意push的时候要考虑minStk为空和number <= minStk.top()两种情况。
class MinStack {
public:
MinStack() {
// do intialization if necessary
}
/*
* @param number: An integer
* @return: nothing
*/
void push(int number) {
dataStk.push(number);
if (minStk.empty() || number <= minStk.top()) {
minStk.push(number);
}
}
/*
* @return: An integer
*/
int pop() {
int dataStkTop = dataStk.top();
int minStkTop = minStk.top();
dataStk.pop();
if (minStkTop == dataStkTop) {
minStk.pop();
}
return dataStkTop;
}
/*
* @return: An integer
*/
int min() {
return minStk.top();
}
private:
stack<int> dataStk;
stack<int> minStk;
};
五刷:Leetcode 155. 题目差不多,稍有不同。
这个版本不如上面的好,minStk的空间没有得到优化。
class MinStack {
public:
MinStack() {
minVal = INT_MAX;
}
void push(int val) {
genStk.push(val);
minVal = min(minVal, val);
minStk.push(minVal);
}
void pop() {
genStk.pop();
minStk.pop();
if (!minStk.empty()) minVal = minStk.top();
else minVal = INT_MAX;
}
int top() {
return genStk.top();
}
int getMin() {
return minStk.top();
}
private:
stack<int> genStk, minStk;
int minVal;
};
/**
* Your MinStack object will be instantiated and called as such:
* MinStack* obj = new MinStack();
* obj->push(val);
* obj->pop();
* int param_3 = obj->top();
* int param_4 = obj->getMin();
*/
稍微优化一下,因为没必要维护minVal, minStk.top()就是minVal。
class MinStack {
public:
MinStack() {
}
void push(int val) {
genStk.push(val);
if (minStk.empty()) minStk.push(val);
else minStk.push(min(val, minStk.top()));
}
void pop() {
genStk.pop();
minStk.pop();
}
int top() {
return genStk.top();
}
int getMin() {
return minStk.top();
}
private:
stack<int> genStk, minStk;
};