每天学习一算法系列(3)--设计包含min函数的栈,要求函数min、push以及pop的时间复杂度都是O(1))

题目:

请设计包含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 &quot;stdafx.h&quot; #include &lt;iostream&gt; #include &lt;assert.h&gt; 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-&gt;psNext; delete m_psCurItem; m_psCurItem = psTemp; } m_nSize = m_nMinValue = 0; } int C_Stack::Pop() { if (0 == m_nSize) { cout &lt;&lt; &quot;Stack is empty.&quot; &lt;&lt; endl; return -1; } assert(NULL != m_psCurItem || 0 != m_nSize); S_ItemNode *psNode = m_psCurItem; int i32RetValue = m_psCurItem-&gt;nValue; m_psCurItem = m_psCurItem-&gt;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-&gt;nValue = i32Value; psNode-&gt;psNext = m_psCurItem; m_psCurItem = psNode; if (0 == m_nSize || i32Value &lt; 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-&gt;nValue; S_ItemNode *psNode = m_psCurItem-&gt;psNext; while (psNode) { if (psNode-&gt;nValue &lt; m_nMinValue) m_nMinValue = psNode-&gt;nValue; psNode = psNode-&gt;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 &lt;&lt; &quot;Stack size is: &quot; &lt;&lt; objStack.GetSize() &lt;&lt; &quot;,Min value is: &quot; &lt;&lt; objStack.GetMinValue() &lt;&lt; endl; objStack.Pop(); cout &lt;&lt; &quot;Stack size is: &quot; &lt;&lt; objStack.GetSize() &lt;&lt; &quot;,Min value is: &quot; &lt;&lt; objStack.GetMinValue() &lt;&lt; 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&lt;typename T, int MAX_SIZE = 100&gt; 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&amp; Top() const; const T&amp; GetMin() const; int Push(const T&amp; val); T Pop(); private: T arrAllItem[MAX_SIZE]; int arrMinIndex[MAX_SIZE]; int nCurLen; int nCurMinPos; }; template&lt;typename T, int SIZE&gt; C_MinStack&lt;T, SIZE&gt;::C_MinStack():nCurLen(0),nCurMinPos(0) {} template&lt;typename T, int SIZE&gt; const T&amp; C_MinStack&lt;T, SIZE&gt;::Top() const { if (IsEmpty()) { throw C_Overflow(); } return arrAllItem[nCurLen - 1]; } template&lt;typename T, int SIZE&gt; const T&amp; C_MinStack&lt;T, SIZE&gt;::GetMin() const { if (IsEmpty()) { throw C_Overflow(); } return arrAllItem[arrMinIndex[nCurMinPos - 1]]; } template&lt;typename T, int SIZE&gt; int C_MinStack&lt;T,SIZE&gt;::Push(const T&amp; val) { if (IsFull()) { throw C_Overflow(); } if (IsEmpty() || val &lt; GetMin()) { arrMinIndex[nCurMinPos++] = nCurLen; } arrAllItem[nCurLen++] = val; return nCurLen; } template&lt;typename T, int SIZE&gt; T C_MinStack&lt;T, SIZE&gt;::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&lt;int&gt; 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 &lt;&lt; &quot;Stack size is: &quot; &lt;&lt; objStack.GetSize() &lt;&lt; &quot;,Min value is: &quot; &lt;&lt; objStack.GetMin() &lt;&lt; endl; objStack.Pop(); cout &lt;&lt; &quot;Stack size is: &quot; &lt;&lt; objStack.GetSize() &lt;&lt; &quot;,Min value is: &quot; &lt;&lt; objStack.GetMin() &lt;&lt; endl; return 0; }</textarea>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值