劍指Offer(面試題22~24)

面試題22:棧的壓入、彈出序列

題目:輸入兩個整數序列,第一個序列表示棧的壓入順序,請判斷第二個序列是否爲該棧的彈出順序。假設壓入棧的所有數字均不相等。例如序列1、2、3、4、5是某棧的壓入順序,序列4、5、3、2、1是該壓棧序列對應的一個彈出序列,但4、3、5、1、2就不可能是該棧序列的彈出序列。

判斷一個序列是不是棧的彈出序列的規律:如果下一個彈出的數字剛好是棧頂數字,那麼直接彈出。如果下一個彈出的數字不在棧頂,我們把壓棧序列中還沒有入棧的數字壓入輔助棧,直到把下一個需要彈出的數字壓入棧頂爲止。如果所有的數字都壓入棧了仍然沒有找到下一個彈出的數字,那麼該序列不可能是一個彈出序列。

bool IsPopOrder(const int* pPush,const int* pPop,int nLength)
{
    bool bPossible = false;

    if(pPush != NULL && pPop != NULL && nLength > 0)
    {
        const int* pNextPush = pPush;
        const int* pNextPop = pPop;

        std::stack<int> stackData;

        while(pNextPop - pPop < nLength)
        {
            while(stackData.empty() || stackData.top() != *pNextPop)
            {
                if(pNextPush - pPush == nLength)
                    break;
                stackData.push(*pNextPush);

                pNextPush++;
            }

            if(stackData.top() != *pNextPop)
                break;

            stackData.pop();
            pNextPop++;
        }

        if(stackData.empty() && pNextPop - pPop == nLength)
            bPossible = true;
    }

    return bPossible;
}

面試題23:從上往下打印二叉樹

題目:從上往下打印出二叉樹的每個結點,同一層的結點按照從左到右的順序打印。例如輸入圖4.5中的二叉樹,則依次打印出8、6、10、5、7、9、11。
二叉樹結點的定義如下:

struct BinaryTreeNode
{
    int                 m_nValue;
    BinaryTreeNode*     m_pLeft;
    BinaryTreeNode*     m_pRight;
};

從上到下打印二叉樹的規律:每次打印一個結點的時候,如果該結點有子結點,則把該結點的子結點放到一個隊列的末尾。接下來到隊列的頭部取出最早進入隊列的結點,重複前面的打印操作,直至隊列中所有的結點都被打印出來爲止。

void PrintFromTopToBottom(BinaryTreeNode* pTreeRoot)
{
    if(!pTreeRoot)
        return;

    std::deque<BinaryTreeNode *> dequeTreeNode;
    dequeTreeNode.push_back(pTreeRoot);

    while(dequeTreeNode.size())
    {
        BinaryTreeNode *pNode = dequeTreeNode.front();
        dequeTreeNode.pop_front();

        printf("%d",pNode->m_nValue);

        if(pNode->m_pLeft)
            dequeTreeNode.push_back(pNode->m_pLeft);

        if(pNode->m_pRight)
            dequeTreeNode.push_back(pNode->m_pRight);
    }
}

面試題24:二叉搜索樹的後序遍歷序列

題目:輸入一個整數數組,判斷數組是不是某二叉搜索樹的後序遍歷的結果。如果是則返回true,否則返回false。假設輸入的數組的任意兩個數字都互不相同。

在後序遍歷得到的序列中,最後一個數字是樹的根結點的值。數組中前面的數字可以分爲兩部分:第一部分是左子樹結點的值,它們都比根結點的值小;第二部分是右子樹結點的值,它們都比根結點的值大。

bool VerifySquenceOfBst(int sequence[],int length)
{
    if(sequence == NULL || length <= 0)
        return false;

    int root = sequence[length -1];

    //在二叉搜索樹中左子樹的結點小於根結點
    int i = 0;
    for(;i < length -1;++i)
    {
        if(sequence[i] > root)
            break;
    }

    //在二叉搜索樹中右子樹的結點大於根結點
    int j=i;
    for(;j< length-1;++j)
    {
        if(sequence[j] < root)
            return false;
    }

    //判斷左子樹是不是二叉搜索樹
    bool left = true;
    if(i > 0)
        left=VerifySquenceOfBst(sequence,i);

    //判斷右子樹是不是二叉搜索樹
    bool right = true;
    if(i < length -1 )
        right = VerifySquenceOfBst(sequence+i,length-i-1);

    return (left && right);

}

參考資料《劍指Offer》

發佈了38 篇原創文章 · 獲贊 17 · 訪問量 10萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章