劍指Offer(面試題6~7)

面試題6:重建二叉樹
題目:輸入某二叉樹的前序和中序遍歷的結果,請重建出該二叉樹。假設輸入的前序遍歷和中序遍歷的結果中都不含重複的數字。假如輸入前序遍歷序列{1,2,4,7,3,5,6,8}和中序遍歷序列{4,7,2,1,5,3,8,6}。二叉樹結點的定義如下:

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

我們可以寫出如下的遞歸代碼根據前序和中序遍歷的順序確定二叉樹結構:

BinaryTreeNode* Construct(int* preorder,int* inorder,int length)
{
    if(preorder == NULL || inorder == NULL || length <= 0)
        return NULL;
    return ConstructCore(preorder,preorder+length-1,
                         inorder,inorder+length-1);
}

BinaryTreeNode* ConstructCore
(
 int* startPreorder,int* endPreorder,
 int* startInorder,int*endInorder
)
 {
     //前序遍歷序列的第一個數字是根結點的值
     int rootValue = startPreorder[0];
     BinaryTreeNode* root = new BinaryTreeNode();
     root->m_nValue = rootValue;
     root->m_pLeft=root->m_pRight=NULL;

     if(startPreorder == endPreorder)
     {
         if(startInorder == endInorder 
            && *startPreorder == *startInorder)
                return root;
         else
            throw std::exception("Invalid input.");
     }

     //在中序遍歷中找到根結點的值
     int* rootInorder = startInorder;
     while(rootInorder<=endInorder && *rootInorder != rootValue)
        ++rootInorder;

     if(rootInorder == endInorder && *rootInorder != rootValue)
        throw std::exception("Invalid input.");

     int leftLength=rootInorder-startInorder;
     int* leftPreorderEnd = startPreorder+leftLength;
     if(leftLength>0)
     {
         //構建左子樹
         root->m_pLeft=ConstructCore(startPreorder + 1,
                                     leftPreorderEnd,startInorder,rootInorder-1);
     }
     if(leftLength<endPreorder-startPreorder)
     {
         //構建右子樹
         root->m_pRight = ConstructCore(leftPreorderEnd+1,endPreorder,rootInorder+1,endInorder);
     }

     return root;
 }

在函數ConstructCore中,我們先根據前序遍歷序列的第一個數字創建根結點,接下來在中序遍歷序列中找到根結點的位置,這樣就能確定左、右子樹結點的數量。在前序遍歷和中序遍歷的序列中劃分了左、右子樹結點的值之後,我們就可以遞歸地調用函數ConstructCore,去分別構建它的左右子樹。

面試題7:用兩個棧實現隊列

題目:用兩個棧實現一個隊列。隊列的聲明如下,請實現它的兩個函數appendTail和deleteHead,分別完成在隊和尾部插入結點和在隊列頭刪除結點的功能。

template <typename T> class CQueue
{
public:
    CQueue(void);
    ~CQueue(void);

    void appendTail(const T& node);
    T deleteHead();

private:
    stack<T> stack1;
    stack<t> stack2;
}

template<typename T> void CQueue<T>::appendTail(const T& element)
{
    stack1.push(element);
}
template<typename T> T CQueue<T>::deleteHead()
{
    if(stack2.size()<=0)
    {
        while(stack1.size()>0)
        {
            T& data =stack1.top();
            stack1.pop();
            stack2.push(data);
        }
    }
    if(stack2.size()==0)
        throw new exception("queue is empty");

    T head = stack2.top();
    stack2.pop();

    return head;
}

參考書籍《劍指Offer》

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