今天內推騰訊實習生一面html
其中問道一個問題是,怎樣在不消除遞歸的狀況下防止棧溢出?(不管如何都要使用遞歸)面試
面試的時候,一點都不知道,只能說使用循環來消除,可是那樣不知足要求,後來看看這篇博客http://blog.zhaojie.me/2009/03/tail-recursion-and-continuation.html 才懂了。算法
還有一個不知道的問題是優先隊列的實現,原來沒有接觸過這種數據結構,因此當時想了半天也不知道。。編程
看《數據結構與算法分析——C語言描述》中有提到,結果發現是我本身沒有理解題目的意思。數組
實現方式能夠見鏈接:http://www.cnblogs.com/wuchanming/p/3809496.html數據結構
《編程之美》中有這樣一個題目:數據結構和算法
隊列中取最大值操做問題,題目描述:spa
假設有這樣一個擁有3個操做的隊列:設計
1 Enqueue(v): 將v加入隊列指針
2 DeQueue:使隊列中的隊首元素刪除並返回此元素
3 MaxElement:返回隊列中的最大元素
請設計一種數據結構和算法,讓MaxElement操做的時間複雜度儘量地低。
隊列是遵照「先入先出」原則的一種複雜數據結構。其底層的數據結構不必定要用數組來實現,還可使用其餘特殊的數據結構來實現,以達到下降MaxElement操做複雜度的目的。
分析與解法:
解法一
這個問題的關鍵在於取最大值的操做,而且考慮但隊列裏面的元素動態增長和減小的時候,如何可以很是快速地把最大值取出。
雖然,最直接的思路就是按傳統方式來實現隊列。利用一個數組或鏈表來存儲隊列的元素,利用兩個指針分別指向隊列的隊首和隊尾。若是採用這種方法,那麼MaxElement操做須要遍歷隊列的全部元素。在隊列的長度爲N的條件下,時間複雜度爲O(N)。
解法二
根據取最大值的要求,能夠考慮用最大堆來維護隊列中的元素。堆中每一個元素都有指針指向它的後續元素。這樣,堆就能夠很快實現返回最大元素的操做。同時,咱們也能保證隊列的正常插入和刪除。MaxElement操做其實就是維護一個最大堆,其時間複雜度爲O(1)。而入隊和出隊操做的時間複雜度爲O(lgN)
開始不太能理解,後來想一想好像是這樣的,好比,隊列是先進先出的,因此用一種數據結構來記錄元素的進出順序,而使用最大堆來維持找到最大值的效率。假如使用queue來存放全部的數據,當入隊的時候直接插入隊尾,而最大堆也須要將加入的值放在堆的最後,而後進行調整,直到知足最大堆。若是是進行訪問最大值,能夠直接訪問堆頂的元素。若是是進行出隊操做,從隊列的首部刪除該元素,並在最大堆中找到該元素,刪除以後,進行調整。這樣既可以達到知足隊列的「先進先出」,也能知足在O(1)的條件下訪問到最大值。
解法三
曾經作過一種相似的題目是最小棧,也就是在O(1)的狀況下訪問到棧中的最小元素。如是想到也可使用這種方式來實現優先隊列,
若是使用兩個數組分別存放,第一個數組按進入的順序存放全部的元素,另外一個數組中存放最大值的下標,另外還用一個變量記錄當前的最大值下標。
實現代碼:
class stack { public: stack() { stackTop=-1; maxStackItemIndex=-1; } void push(Type x) { stackTop++; if(stackTop>=Max) ; //棧滿 else { stackItem[stackTop]=x; if(x>Max()) { link2NextMaxItem[stackTop]=maxStackItemIndex; maxStackItemIndex=stackTop; } else link2NextMaxItem[stackTop]=-1; } } Type Pop() { Type ret; if(stackTop<0) ThrowException(); //已經沒有元素來,因此不能pop else { ret=stackItem[stackTop]; if(stackTop==maxStackItemIndex) { maxStackItemIndex=link2NextMaxItem[stackTop]; } stackTop--; } return ret; } Type Max() { if(maxStackItemIndex>=0) return stackItem[maxStackItemIndex]; else return -INF; } private: Type stackItem[MAXN]; int stackTop; int link2NextMaxItem[MAXN]; int maxStackItemIndex; };
這裏,維護一個最大值的序列來保證Max操做的時間複雜度爲O(1),至關於用空間複雜度換取了時間複雜度。
若是可以用棧有效第實現隊列,而棧的Max操做又很容易,那麼隊列的Max操做也就能有效地完成了。