题目:定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的min函数。在该栈中,调用min、push及pop的时间复杂度都是O(1)。
我们或许会想到在栈里添加一个成员变量存放最小的元素。
具体思路为:每次压入一个新元素进栈的时候,如果该元素比当前最小的元素还要小,则更新最小元素。
但是上述办法存在一个问题:如果我们做弹出操作,恰好弹出的是栈当前的最小元素?那么如何得到下一个最小的元素呢?
为此,在push一个元素的时候,我们需要辅助栈保存之前的最小元素。
具体做法为:每次push进一个元素val的时候,我们都将val与当前辅助栈的栈顶元素(最小元素)比较,然后将两者的较小者压入辅助栈,那么就能保证辅助栈的栈顶一直都是最小元素。当最小元素从数据站内被弹出之后,同时弹出辅助栈的栈顶元素,此时辅助栈的新栈顶元素就是下一个最小值。
待压入序列为:3、4、2、1、0;具体操作、数据栈、辅助栈以及最小值如下表所示
具体代码如下:
StackWithMin.hpp
1 // StackWithMin.hpp 2 #ifndef STACKWITHMIN 3 #define STACKWITHMIN 4 5 #include <stack> 6 #include <assert.h> 7 8 template <typename T> 9 class StackWithMin 10 { 11 public: 12 StackWithMin() { } 13 ~StackWithMin() { } 14 15 const T& top()const; 16 17 bool empty()const; 18 size_t size()const; 19 20 void push(const T &elem); 21 void pop(); 22 23 const T& min()const; 24 25 private: 26 std::stack<T> m_data; // 数据栈 27 std::stack<T> m_tmp; // 辅助栈 28 }; 29 30 template <typename T> 31 const T& StackWithMin<T>::top()const 32 { 33 return m_data.top(); 34 } 35 36 template <typename T> 37 bool StackWithMin<T>::empty()const 38 { 39 return m_data.empty(); 40 } 41 42 template <typename T> 43 size_t StackWithMin<T>::size()const 44 { 45 return m_data.size(); 46 } 47 48 template <typename T> 49 void StackWithMin<T>::push(const T &elem) 50 { 51 // 放入数据栈 52 m_data.push(elem); 53 54 // 放入辅助栈 55 // 如果比现有最小值小,则push该elem;如果比现有最小值大,则push辅助栈的栈顶 56 if(m_tmp.empty() || m_tmp.top() > elem) 57 m_tmp.push(elem); 58 else 59 m_tmp.push(m_tmp.top()); 60 } 61 62 template <typename T> 63 void StackWithMin<T>::pop() 64 { 65 assert(!m_data.empty() || !m_tmp.empty()); 66 67 m_data.pop(); 68 m_tmp.pop(); 69 } 70 71 template <typename T> 72 const T& StackWithMin<T>::min()const 73 { 74 return m_tmp.top(); 75 } 76 77 #endif/* STACKWITHMIN */
测试代码如下:
main.cpp
1 // main.cpp 2 #include "StackWithMin.hpp" 3 #include <iostream> 4 #include <time.h> 5 #include <stdlib.h> 6 using namespace std; 7 8 int main(int argc, char const *argv[]) 9 { 10 srand(time(NULL)); 11 StackWithMin<int> st; 12 13 int n = 10; 14 15 while(n--) 16 { 17 int num = rand() % 100; 18 cout << "Push num " << num; 19 st.push(num); 20 cout << ", Test " << (10-n) << ": Min num is " << st.min() << endl; 21 } 22 cout << "The size is: " << st.size() << endl; 23 24 while(++n < 5) 25 { 26 st.pop(); 27 } 28 cout << "The min num is: " << st.min() << endl; 29 cout << "The size is: " << st.size() << endl; 30 31 return 0; 32 }
本文完。