题目:
定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的函数,在该栈中,调用min,push,pop的时间复杂度都是O(1)。
分析:
如果想让其时间复杂都为1的话,那么就需要记录栈中的最小值,如果我们进行比较再入栈,那么push的时间复杂度就不只是1了,所以这种想法是不行的,如果我们记录一个最小值虽然能满足,但是当这个最小值被弹出之后就不能马上找到剩下元素的最小值了,所以我需要一个容器来记录每一个最小值。
那么我们可以再来一个栈,这个栈中定义最小元素,如果一个数字进入1栈,那么我们就比较一下,如果这个数比2栈中的数字小就进入2栈,如果比2栈中的数大就把2栈当前的数字再压入2栈,这样就能保证2栈栈顶的元素是1栈中最小的。当1栈弹出数字之后,2栈也相应的往外弹出。无论怎么弹栈和进栈都能保证2栈中的栈顶元素是1栈中最小的。
思路理清了代码就很简单了
void PushStack(int value)
{
t1.push(value);
if(t2.empty())
t2.push(value);
else
{
int min = t2.top();
if(min>value)
t2.push(value);
else
t2.push(min);
}
}
int PopStack()
{
int result = -1;
if(!t1.empty())
{
t1.pop();
result = t2.top();
t2.pop();
}
if(result == -1)
cout<<"栈空了"<<endl;
return result;
}
void FindMin()
{
if(!t2.empty())
cout<<t2.top()<<endl;
else
cout<<"栈空了,找不到最小元素"<<endl;
}
思维扩展:
如果说这个题目中不是栈而是队列呢?
我们之前做过两个栈模拟队列,两个队列模拟栈,然后再加上我们刚刚做了上面的分析,是不是能把这个两个点结合起来,就能解决问题呢?
我们可以试一下。
首先是用两个栈来模拟队列,如果我们需要求最小值,那么还需要两个栈来存储刚才的两个栈。这样我们总共有了四个栈。
当队列里进入2 1 3后,我们来用栈模拟,此时A栈中一次进入2 1 3 ,A的最小栈中的一次存入2 1 1 ,当2从队列中弹出之后,那么就要从A栈向B栈压入。此时B栈为3 1 2,将2从B栈中弹出,每一次都是从B栈弹出来模拟出队列,进队列是从A栈进入。只有当B栈空了才从A栈弹入B栈中,最小值是比较两个栈顶元素谁最小。
下面是代码,写的挺乱,并且还有好多都是直接粘贴的,没有做成函数,凑合着看吧
stack<int> ta,tam,tb,tbm;
void PushQueue(int value)
{
ta.push(value);
if(tam.empty())
tam.push(value);
else
{
int min = tam.top();
if(min > value)
tam.push(value);
else
tam.push(min);
}
}
void PopQueue()
{
if(tb.empty())
{
while(!ta.empty())
{
int value = ta.top();
tb.push(value);
if(tbm.empty())
tbm.push(value);
else
{
int min = tbm.top();
if(min > value)
tbm.push(value);
else
tbm.push(min);
}
}
}
if(tb.empty())
{
cout<<"队列已空,不能弹出元素"<<endl;
return ;
}
tb.pop();
tbm.pop();
}
void FindMin()
{
if(tb.empty())
{
while(!ta.empty())
{
int value = ta.top();
tb.push(value);
if(tbm.empty())
tbm.push(value);
else
{
int min = tbm.top();
if(min > value)
tbm.push(value);
else
tbm.push(min);
}
ta.pop();
}
}
if(tam.empty() && tbm.empty())
{
cout<<"队列中没有元素"<<endl;
return ;
}
if(tam.empty())
cout<< tbm.top()<<endl;
else
{
int mina = tam.top();
int minb = tbm.top();
int min = mina < minb ? mina : minb ;
cout<< min <<endl;
}
}