发布时间:2023-03-12 17:00
程序员代码面试指南 IT名企算法与数据结构题目最优解 第一问
有这样的一个问题:
设计一个栈,实现栈的基本功能的基础上,在实现返回栈中的最小元素操作。
这个问题看似不难,只要在栈push每一个元素的时候将这个元素和一个最小数min进行大小比较,小于min就把这个元素的值赋给min,如此一来就可以得出所有入栈元素的最小值。但是这有一个问题:即将栈顶元素pop出来之后,如何判断此刻栈元素中的最小值?
由于栈本身不支持随机访问和加一减一的访问模式,我们不能通过遍历栈来获取最小值。那么似乎只有这样一个办法:即pop顶元素时将剩下的所有元素逐个pop出来,然后逐个和最小数min比较,小于min就把这个元素的值赋给min,然后压入另一个栈,完成所有元素的出栈-入栈,并且找到min之后,再来把元素出栈入栈放回到原来的栈中。
这样一来开销非常大,不太实用。
程序员代码面试指南 IT名企算法与数据结构题目最优解 给出了他的方法,我觉得非常不错。
他的核心思路是用另外一个栈的元素来记录目标栈的每一个数据段的最小值。
这句话看起来非常难理解,也确实不好总结,所以下面来详细说明一下。
假设现在压入了3,4,5,1,2,1这几个数。那么栈的存储模型现在如下图所示。
左边是我们的目标栈,右边是指示左边最小元素的栈。
聪明的同学可能已经明白了,右边的每一个元素代表着左边栈对应位以下的数据段的最小值(可以忽略’无’,实际上右边栈中只有3个元素)。例如右边从上往下的第二个1,对应着左边栈从上往下的第二个1,那么这就是说,左边栈底的四个元素1,5,4,3中最小的元素就是1!其他的同理可推。
那么也就是说,右边栈的栈顶的值永远代表着左边栈的最小元素值!
那么如此一来代码就简单了。
现在我重写一个类,这个类实现一般的pop,push功能,外加一个getmin函数
class MinStack
{
private:
stack<int> s;//左边的栈,目标栈
stack<int> smin;//右边的栈,最小元素栈
public:
void push(int a)
{
if(s.empty()==true)
{
s.push(a);
smin.push(a);
}
else
{
if(smin.top()>=a)
smin.push(a);
s.push(a);
}
}
int pop()
{
int value;
if(s.empty()==true)
{
cout<<"Empty Stack!"<return -1;
}
if(s.top()==smin.top())
smin.pop();
value=s.top();
s.pop();
return value;
}
int getmin()
{
if(s.empty()==true)
{
cout<<"Empty Stack!"<return -1;
}
return smin.top();
}
};
void main()
{
MinStack s;
s.push(5);
s.push(2);
s.push(1);
s.push(6);
s.push(7);
s.push(6);
cout<cout<
运行结果:
1
5