题目要求
实现一个栈,要求实现Push(出栈)、Pop(入栈)、Min(返回最小值的操作)的时间复杂度为O(1)
首先针对这道题有多重解决方案。
1、定义两个栈,一个正常栈,另一个栈的栈顶始终保存整个栈内的最小值。
思路如下:
- 无论Push什么数据,正常栈肯定直接Push进去。
- 而当新Push的数据大于最小栈的栈顶时,最小栈将自己的栈顶再次Push一遍。
- 而当新Push的数据小于最小栈的栈顶时,意思是该数据现在是整个栈中的最小值,则将该值也直接Push进最小栈
这种思路的Pop和就很简单了,每次Pop时,将两个栈的栈顶都Pop出去就好了,求Min的话,直接返回最小栈的栈顶。
基于这种思路,写出如下代码:
template<class T>
class MinStack
{
public:
void Push2(const T value)
{
if (_s.empty() || _min.top() > value)
{
_s.push(value);
_min.push(value);
}
else
{
_s.push(value);
_min.push(_min.top());
}
}
void Pop()
{
_s.pop();
_min.pop();
}
T Min()
{
return _min.top();
}
private:
stack<T> _s;
stack<T> _min;
};
2、在第一种的思路中,最小栈将当前最小的值重复存放了好多份,可不可以只存一份呢?加上引用计数!
如果直接只存一份的话,会出现下面这种情况。
每次Pop时,如果待Pop的值大于最小栈中的栈顶数据,就只Pop正常栈,但是如果栈中有两个相同元素呢?
template <class T>
class MinStack
{
public:
void Push(const T value)
{
if (_s.empty() || _min.top().first > value)
{
_s.push(value);
_min.push(make_pair(value, 1));
}
else if (_min.top().first == value)
{
_s.push(value);
_min.top().second += 1;
}
else
{
_s.push(value);
}
}
void Pop()
{
T top = _s.top();
if (top == _min.top().first)
{
if (_min.top().second > 1)
--_min.top().second;
else
_min.pop();
_s.pop();
}
else
{
_s.pop();
}
}
int Min()
{
return _min.top().first;
}
private:
stack<int> _s;
stack<pair<int, int>> _min;
};
3、使用一个栈,每次Push两个值,一个正常值,一个是最小值,什么意思呢?
template <class T>
class MinStack
{
public:
void Push(const T value)
{
if (_s.empty() || _s.top() > value)
{
_s.push(value);
_s.push(value);
}
else
{
T top = _s.top();
_s.push(value);
_s.push(top);
}
}
void Pop()
{
_s.pop();
_s.pop();
}
int Min()
{
return _s.top();
}
private:
stack<int> _s;
};
4、基于第三种方法,可以每次Push一个键值对,一个保存正常值,一个保存最小值,和第三种思想是一样的。
template <class T>
class MinStack
{
public:
void Push(const T& value)
{
if (_s.empty() || _s.top().second > value)
{
_s.push(make_pair(value, value));
}
else
{
_s.push(make_pair(value, _s.top().second));
}
}
void Pop()
{
_s.pop();
}
T Min()
{
return _s.top().second;
}
private:
stack<pair<int, int>> _s;
};