您的位置:首页 > 其它

17_7_19:实现一个栈要求实现入栈、出栈、获得最小值的时间复杂度为O(1)

2017-07-19 23:58 246 查看
问题描述:

实现一个栈Stack,要求实现Push(出栈)、Pop(入栈)、Min(返回最小值的操作)的时间复杂度为O(1) 。

难点分析:

首先,我们知道,在栈的实现中,入栈、出栈操作的时间复杂度都是O(1)。

难就难在返回最小值的操作的时间复杂度。如果有一个值来存储的话,到时可以,但是,当有入栈,出栈操作时,这个最小值是不断变换着的。

所以,难点可以看成是:最小值如何存储,才能满足栈中元素的动态变换呢?

思路:

虽然栈中元素可能动态变换,但是也要满足“后进先出”的原则。

当入栈的元素,小于存储的最小值时,我们要更新最小值;当最小值出栈时,我们也要更新最小值。

也就是说,我们也要动态的存储栈中出现过的最小值,知道这个元素出栈。

这样,我们可以利用两个栈s1,s2,一个专门存储数据集合,一个专门存储数据中的最小值集合。

当一个数据data入栈时,存储到第一个栈s1中,并且和第二个栈s2中的栈顶元素s2.top()比较大小。如果data<=s2.top(),那么也存储到s2中,这样当返回最小值时,直接就可以从s2中取,时间复杂度O(1)。

当一个数据data出栈时,和第二个栈中元素s2.top()比较,如果data=s2.top。则说明,此时出栈的元素是最小值。那么就要s1,s2都要出栈。来更新数据栈,以及最小值栈。此时,返回最小值时,直接就可一个从s2中取,时间复杂度O(1)。

可以发现,利用栈的“后进先出”规则,可以用来,动态更新最小值结婚。并且,位于栈顶的永远是最小的。从上往下,最小值数据依次变大。

值得注意的是:数据入栈时和最小值栈顶元素比较时,一定是“<=”,这样可以避免多个值相同数据,出栈时造成的错误。

实现代码:

#include <iostream>
#include <stack>
#include <cassert>
#include <time.h>  //用来生成随机数

template <typename T>
class Stack
{
public:
void Push(const T& data)
{
_s_1.push(data);

//当_s_2为空时,_s_1原来肯定也为空,实现的栈中数据,只有一个。
if (_s_2.empty())
{
_s_2.push(data);
return;
}

//如果,入栈数据小于等于实现栈中的最小值,也入栈
T &min = _s_2.top();
if (data <= min)
_s_2.push(data);
}

void Pop()
{
if (_s_1.empty()) //_s_1为空,_s_2也为空,当做一种情况。
assert(0);

//如果出栈元素,等于最小值,则,两个一起出栈,否则,只有数据出栈,最小值不变
if (_s_1.top() == _s_2.top())
_s_2.pop();
_s_1.pop();
}

T& Get_Min()
{
if (_s_2.empty())
assert(0);

return _s_2.top();
}

private:
std::stack<T> _s_1;
std::stack<T> _s_2;
};


测试用例:

int main()
{
Stack<int> s;

srand((unsigned)time(NULL)); //以时间作为随机数种子
for (int i = 0; i < 100; ++i)
s.Push(rand());

//测试用例,输出应该是从小到大递增
for (int i = 0; i < 100; ++i)
{
std::cout <<i<<":"<< s.Get_Min() << std::endl;
s.Pop();
}

system("pause");
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐