剑指Offer:面试题21 包含min函数的栈

/*
包含min函数的栈:
定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的min函数。在该栈中,调用min、push及pop的
时间复杂度都是O(1)


分析:
如果直接遍历来找,需要O(n)
如果要实现是O(1),基本只能靠hash了,栈的最小元素绝对应该放到栈顶或在栈顶寻找到,否则不可能是O(1)
如何将最小元素放到栈顶?每次放的时候,将大的放在下面,小的放在上面?


关键:
采用一个辅助栈。因为考虑到最小的数弹出之后,怎么才能取得次最小的数。因此,这里的辅助栈:
每次压入一个元素,要与后面的元素比较,较小的元素才能成为最小的元素。


模拟:
数据栈里面压入3,把最小值3压入辅助栈。往数据栈里面压入4,因为4大于3,因此我们仍压入3。数据栈中压入2,
辅助栈中,我们把最小值更新为2,并把2压入辅助栈。
当最小元素从数据栈内被弹出时,同时弹出辅助栈的栈顶元素。




输入:
输入可能包含多个测试样例,输入以EOF结束。
对于每个测试案例,输入的第一行为一个整数n(1<=n<=1000000), n代表将要输入的操作的步骤数。
接下来有n行,每行开始有一个字母Ci。
Ci=’s’时,接下有一个数字k,代表将k压入栈。
Ci=’o’时,弹出栈顶元素。
输出:
对应每个测试案例中的每个操作,
若栈不为空,输出相应的栈中最小元素。否则,输出NULL。
样例输入:
7
s 3
s 4
s 2
s 1
o
o
s 0
样例输出:
3
3
2
1
2
3
0
*/


/*
关键:
1 bool empty()//添加一个判空函数,用于NULL的输出
2 void MinStack<T>::push(const T& ele)//压入元素
{
dataStack.push(ele);//数据栈无论何时都压入,因此提出来
if(minStack.empty())//如果栈为空,那么直接在数据栈和辅助栈中压入元素
{
minStack.push(ele);
}
else//非空时,就要在辅助栈中进行比较了
{
if(ele < minStack.top())//如果当前元素小于栈顶元素(即最小元素),则将该元素压入栈中
{
minStack.push(ele);
}
else//经典,若当前元素比栈顶元素小,那么再将栈顶元素压入栈中,这样就保证了辅助栈的栈顶始终是最小的元素
{
minStack.push(minStack.top());
3 stack<T> dataStack;
stack<T> minStack;//使用辅助栈
*/


#include <iostream>
#include <stack>


int INF = 1000000000;


using namespace std;
template<typename T>
class MinStack
{
public:
MinStack(){}
~MinStack(){}
void push(const T& ele);
void pop();
T& min();
bool empty()//添加一个判空函数,用于NULL的输出
{
if(minStack.empty() && dataStack.empty())
{
return true;
}
else
{
return false;
}
}
private:
stack<T> dataStack;
stack<T> minStack;//使用辅助栈
};


template<typename T>
void MinStack<T>::push(const T& ele)//压入元素
{
dataStack.push(ele);//数据栈无论何时都压入,因此提出来
if(minStack.empty())//如果栈为空,那么直接在数据栈和辅助栈中压入元素
{
minStack.push(ele);
}
else//非空时,就要在辅助栈中进行比较了
{
if(ele < minStack.top())//如果当前元素小于栈顶元素(即最小元素),则将该元素压入栈中
{
minStack.push(ele);
}
else//若当前元素比栈顶元素小,那么再将栈顶元素压入栈中,这样就保证了辅助栈的栈顶始终是最小的元素
{
minStack.push(minStack.top());
}
}
}


template<typename T>
void MinStack<T>::pop()//弹出元素,应该同时将数据栈和最小栈中元素均弹出。但是只打印最小栈的栈顶元素
{
//先判空才能弹出
if(!dataStack.empty() && !minStack.empty())
{
dataStack.pop();
minStack.pop();
}
}


template<typename T>
T& MinStack<T>::min()
{
if(!minStack.empty() && !dataStack.empty())
{
return minStack.top();
}
else
{
return INF;
}
}




void process()
{
int n;
char ch;
int num;
MinStack<int> mStack;
while(cin >> n)
{
for(int i = 0 ; i < n ; i++)
{
cin >> ch;
if('s' == ch)
{
cin >> num;
mStack.push(num);
cout << mStack.min() << endl;
}
else if('o' == ch)//弹出
{
mStack.pop();
if(!mStack.empty())
{
cout << mStack.min() << endl;
}
else
{
cout << "NULL" << endl;
}
}
}
}
}


int main(int argc,char* argv[])
{
process();
getchar();
return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值