棧&佇列面試題之實現一個棧...(Push,Pop,Min)
阿新 • • 發佈:2019-02-09
實現一個棧,要求實現Push(壓棧),Pop(出棧),Min(返回最小值的操作)的時間複雜度為O(1)
我們知道棧是後進先出的一種資料結構,這種資料結構只允許在棧頂進行插入刪除,所以要實現棧這種資料結構最好的結構就是順序表.當尾插尾刪多的時候,連結串列存在開闢空間和刪除空間的時間消耗所以此時順序表優於連結串列.結構選好之後就是如何求出棧的元素的最小值了?
思路一:
如果一次可以將同一個資料進行兩次壓棧
一.要壓入的資料比棧頂的資料大
(1).將原來棧頂的元素儲存起來再Pop掉
(2).將新元素壓棧,再將原來棧頂的元素壓棧
二.要壓入的資料比棧頂的資料小
直接將該資料兩次壓棧
如果每次都如此壓棧的話到最後棧頂的元素一定是所有資料中最小的元素,而且也不會改變入棧的順序
思路二:
利用兩個棧,一個棧按照正確的壓棧順序壓棧,一個棧用來儲存最小值;
(1).如果Stack1是空棧或者要入棧的元素小於Stack2的棧頂元素則將該資料即壓入Stack1,也壓入Stack2中
(2).如果要入棧的元素大於Stack2的棧頂元素則只需要將該資料壓入Stack1中
此時Stack2中一定儲存的是原來入棧元素的最小值了
以上兩種想法都是以空間換時間,時間複雜度為O(1)
思路一的實現:
//兩個元素為一組,棧頂為最小的元素 template<typename T> class MinStack { public: void Push(const T& d) { if(_ptr.empty() || d <= _ptr.top()) //要入棧的元素小於棧頂元素 { _ptr.push(d); _ptr.push(d); } else { T mindata=_ptr.top(); _ptr.push(d); _ptr.push(mindata); } } void Pop() { assert(!_ptr.empty()); _ptr.pop(); _ptr.pop(); } T& MinData() { return _ptr.top(); } T& top() { assert(!_ptr.empty()); T mindata=_ptr.top(); _ptr.pop(); T &ret=_ptr.top(); _ptr.push(mindata); return ret; } protected: stack<T> _ptr; };
思路二的實現:
//利用兩個棧,其中一個儲存最小值
template<typename T>
class MinStack2
{
public:
void Push(const T& d)
{
if(_ptr1.empty() || d <= _ptr2.top())
{
_ptr1.push(d);
_ptr2.push(d);
}
else
{
_ptr1.push(d);
}
}
void Pop()
{
assert(!_ptr1.empty());
if(_ptr1.top() == _ptr2.top())
{
//當兩個棧的棧頂元素相同時同時出棧
_ptr1.pop();
_ptr2.pop();
}
_ptr1.pop();
}
T& MinData()
{
return _ptr2.top();
}
protected:
stack<T> _ptr1; //存放資料
stack<T> _ptr2; //最小值
};
注意:
在想法二的Pop函式的實現中_ptr2也需要調整,當兩個棧棧頂元素一致時才可調整_ptr2的棧頂元素,否則棧的最小值會一直是原先的最小值,無法動態修改.
test.cpp
void testMinStack()
{
MinStack<int> ms;
ms.Push(5);
ms.Push(1);
ms.Push(2);
ms.Push(3);
ms.Pop();
cout<<ms.top()<<endl; //3
cout<<"最小元素為:";
cout<<ms.MinData()<<endl;
}
void testMinStack2()
{
MinStack2<int> ms2;
ms2.Push(5);
ms2.Push(3);
ms2.Push(6);
ms2.Push(0);
ms2.Push(2);
cout<<"最小元素為:";
cout<<ms2.MinData()<<endl; //0
ms2.Pop();
ms2.Pop();
cout<<"最小元素為:";
cout<<ms2.MinData()<<endl; //3
}
int main()
{
//testMinStack();
testMinStack2();
system("pause");
return 0;
}
通過測試以上兩種程式碼都是可實現的...