面试题7:重建二叉树

一.题目

输入某二叉树的前序遍历和中序遍历结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{ 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;
}

BinaryTree* Construc(int* preorder,int* inorder,int length){
    if(preorder == nullptr || inorder == nullptr || length <= 0)
        return nullptr;

    return ConstrucCore(preorder,preorder+length-1.inorder,inorder+length-1);

}

BinaryTreeNode* ConstrucCore(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 = nullptr;

    if(stratPreorder == endPreorder){

        if(startInorder == endInorder)
            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 = ConstrucCore(startPreorder+1,leftPreorderEnd,startInorder,rootInorder-1);

    //建立右子树
    if(leftLength < endPreorder - startPreorder)
        root->m_pRight = ConstrucCore(leftPreorderEnd+1,endPreorder,rootInorder+1,endInorder);

    return root;
}

四.本题考点

  1. 考查应聘者对二叉树的前序遍历和中序遍历的理解程度。只有对二叉树的不同遍历算法有了深刻的理解,应聘者才有可能在遍历序列中划分出左右子树对应的子序列。
  2. 考查应聘者分析复杂问题的能力。我们把构建二叉树的大问题分解为构建左右子树的两个小问题。我们发现小问题和大问题在本质上是一致的,因此可以用递归的方式解决。
posted @ 2018-10-30 11:02  OVS98  阅读(143)  评论(0)    收藏  举报