题目:
请设计包含min函数的栈。
定义栈的数据结构,要求添加一个min函数,能够得到栈的最小元素。
要求函数min、push以及pop的时间复杂度都是O(1)。
题目来源于:http://topic.csdn.net/u/20101023/20/5652ccd7-d510-4c10-9671-307a56006e6d.html
思路:
按照题目所给出的要求,我们开始想到的是设计一个类,然后类里面用一个自定义的成员变量结构体来维护栈的结构,而且有一个成员变量来记录栈的最小值Min,但向栈中Push时,把Push进来的值和Min值比较,如果小于Min的话,就把Min值设置为当前Push进去的值,但调用Pop的时候,如果Pop出去的值大于最小值那么就不改变Min值,如果Pop出去的值如果等于Min值,这时候就要重新调整Min值,我们最容易想到的解法是遍历该Stack,重新找出最小值,显然时间复杂度为0(n), 但是题目要求要保证时间复杂度为0(1),所以要想想其他的解法.如果不保证min函数的时间复杂度是0(1),那么我们的代码如下:
<textarea class="cpp" rows="15" cols="50" name="code">/*------------------------------------ 最初版本,但是Min函数的时间复杂度为0(n) copyright yuucyf. -------------------------------------*/ #include "stdafx.h" #include <iostream> #include <assert.h> using namespace std; class C_Stack { typedef struct tagItemNode { int nValue; tagItemNode *psNext; tagItemNode() { nValue = 0; psNext = NULL; } }S_ItemNode; private: S_ItemNode *m_psCurItem; int m_nMinValue; int m_nSize; private: void RefindMinValue(); public: C_Stack(); ~C_Stack(); public: int GetSize() { return m_nSize; } int GetMinValue() { return m_nMinValue; } int Push(int i32Value); int Pop(); }; C_Stack::C_Stack():m_psCurItem(NULL), m_nMinValue(0), m_nSize(0) { } C_Stack::~C_Stack() { S_ItemNode *psTemp = NULL; while (m_psCurItem) { psTemp = m_psCurItem->psNext; delete m_psCurItem; m_psCurItem = psTemp; } m_nSize = m_nMinValue = 0; } int C_Stack::Pop() { if (0 == m_nSize) { cout << "Stack is empty." << endl; return -1; } assert(NULL != m_psCurItem || 0 != m_nSize); S_ItemNode *psNode = m_psCurItem; int i32RetValue = m_psCurItem->nValue; m_psCurItem = m_psCurItem->psNext; m_nSize--; delete psNode; if (i32RetValue == m_nMinValue) RefindMinValue(); return i32RetValue; } int C_Stack::Push(int i32Value) { S_ItemNode *psNode = new S_ItemNode; assert(NULL != psNode); psNode->nValue = i32Value; psNode->psNext = m_psCurItem; m_psCurItem = psNode; if (0 == m_nSize || i32Value < m_nMinValue) { m_nMinValue = i32Value; } return ++m_nSize; } void C_Stack::RefindMinValue() { if (0 == m_nSize) return; assert (NULL != m_psCurItem); m_nMinValue = m_psCurItem->nValue; S_ItemNode *psNode = m_psCurItem->psNext; while (psNode) { if (psNode->nValue < m_nMinValue) m_nMinValue = psNode->nValue; psNode = psNode->psNext; } } int _tmain(int argc, _TCHAR* argv[]) { C_Stack objStack; objStack.Push(2); objStack.Push(4); objStack.Push(8); objStack.Push(6); objStack.Push(12); objStack.Push(10); objStack.Push(15); objStack.Push(1); objStack.Push(16); cout << "Stack size is: " << objStack.GetSize() << ",Min value is: " << objStack.GetMinValue() << endl; objStack.Pop(); cout << "Stack size is: " << objStack.GetSize() << ",Min value is: " << objStack.GetMinValue() << endl; return 0; }< /textarea>
思路二:为了使min操作的复杂度将为O(1),就不能遍历整个栈,因此需要时刻保存min值的索引,用以min方法的请求,再者,若在连续使用pop()方法后,仍能使min方法返回正确的最小值,则仅保存一个min值索引是不够的,使用辅助栈是我目前能想到的唯一可行办法,代码如下:
<textarea class="cpp" rows="15" cols="50" name="code">/*------------------------------------ copyright leeyunce. Modified by yuucyf -------------------------------------*/ class C_Overflow {}; template<typename T, int MAX_SIZE = 100> class C_MinStack { public: C_MinStack(); bool IsEmpty() const { return nCurLen == 0; } bool IsFull() const { return nCurLen == MAX_SIZE; } int GetSize() const { return nCurLen; } const T& Top() const; const T& GetMin() const; int Push(const T& val); T Pop(); private: T arrAllItem[MAX_SIZE]; int arrMinIndex[MAX_SIZE]; int nCurLen; int nCurMinPos; }; template<typename T, int SIZE> C_MinStack<T, SIZE>::C_MinStack():nCurLen(0),nCurMinPos(0) {} template<typename T, int SIZE> const T& C_MinStack<T, SIZE>::Top() const { if (IsEmpty()) { throw C_Overflow(); } return arrAllItem[nCurLen - 1]; } template<typename T, int SIZE> const T& C_MinStack<T, SIZE>::GetMin() const { if (IsEmpty()) { throw C_Overflow(); } return arrAllItem[arrMinIndex[nCurMinPos - 1]]; } template<typename T, int SIZE> int C_MinStack<T,SIZE>::Push(const T& val) { if (IsFull()) { throw C_Overflow(); } if (IsEmpty() || val < GetMin()) { arrMinIndex[nCurMinPos++] = nCurLen; } arrAllItem[nCurLen++] = val; return nCurLen; } template<typename T, int SIZE> T C_MinStack<T, SIZE>::Pop() { if (IsEmpty()) { throw C_Overflow(); } T retVal = arrAllItem[--nCurLen]; if (nCurLen == arrMinIndex[nCurMinPos-1]) { nCurMinPos--; } return retVal; } int _tmain(int argc, _TCHAR* argv[]) { C_MinStack<int> objStack; objStack.Push(2); objStack.Push(4); objStack.Push(8); objStack.Push(6); objStack.Push(12); objStack.Push(10); objStack.Push(15); objStack.Push(1); cout << "Stack size is: " << objStack.GetSize() << ",Min value is: " << objStack.GetMin() << endl; objStack.Pop(); cout << "Stack size is: " << objStack.GetSize() << ",Min value is: " << objStack.GetMin() << endl; return 0; }</textarea>