騰訊電話面試

今天內推騰訊實習生一面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操做也就能有效地完成了。