实现一个栈,实现入栈,出栈,求最小值,时间复杂度为O(1)

时间:2021-08-20 15:12:56

题目:

实现一个栈,实现入栈,出栈,求栈中最小值,时间复杂度为O(1)

方案一:

设计栈中元素类型为一个包含元素值和当前栈中所有元素的最小值的对象

入栈时,将对象入栈,当前元素的值小于栈中最小值时,就将当前元素的最小值设为当前元素的值,保持栈顶的元素对象的最小值一直是栈中所有元素的最小值

出栈时,将元素对象弹出

栈中元素的最小值:栈顶的元素对象的最小值

方案一缺点:每次压入栈中的元素中包含最小值的一个项,当最小值一直不变时,保存多份最小值,浪费空间

方案二:

利用两个栈,一个栈是维护入栈出栈的栈,另一个栈保存当前栈中所有元素的最小值

入栈时,将该元素压入第一个栈中,若该元素小于等于栈中最小值时,就将该元素的值压入最小值的栈中

出栈时,若第一个栈栈顶元素和维护最小值的栈的栈顶元素相等,则将两个栈顶元素都弹出

若两栈顶元素不相等,则将第一个栈顶元素弹出,第二个栈中元素不变


为什么是小于等于

因为当有多个相等的元素都是最小值时,如果只保存小于最小值的值,那当栈中最小元素出栈时,第二个栈中栈顶元素出栈,那么栈中最小值就变了,例如:

栈中元素为:4,2,6,5,8,3,2,2

最小值的栈为:4,2

当2出栈时,最小值栈中的元素2出栈,则整个栈的最小值就变成4了,实际上最小值还是2


程序代码如下:

//实现一个栈,实现入栈,出栈,求最小值,时间复杂度为O(1);
template<class T>
class Stack
{
public:
void Push(const T& d)
{
s.push(d);
if (s.size() == 1)
min.push(s.top());
else
{
if (s.top() <= min.top())
{
min.push(s.top());
}
}
}
void Pop()
{
if (!s.empty())
{
if (s.top() == min.top())
min.pop();
s.pop();
}
}
T& Min()
{
return min.top();
}
size_t Size()
{
return s.size();
}
bool Empty()
{
return s.empty();
}
T& Top()
{
return s.top();
}
private:
stack<T> s;
stack<T> min;
};

测试代码:

void TestStackMin()
{
Stack<int> s;
s.Push(4);
s.Push(3);
s.Push(2);
s.Push(2);
cout << s.Size() << endl;
cout << s.Min() << endl;;
while (!s.Empty())
{
cout << s.Top() << " " << endl;
cout << "min:"<<s.Min() << endl;
s.Pop();
}


}