面试题7:重建二叉树

一.题目

输入某二叉树的前序遍历和中序遍历结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{ 1, 2, 4, 7, 3, 5, 6, 8 }和中序遍历序列{ 4, 7, 2, 1, 5, 3, 8, 6 },则重建的二叉树如图所示:

70

二.思路

首先根据前序遍历序列找到根节点(序列第一个元素即为根节点),然后在中序遍历中找到根节点位置,然后递归确定左子树和右子树,即可完成二叉树的构建。

三.代码

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. 考查应聘者分析复杂问题的能力。我们把构建二叉树的大问题分解为构建左右子树的两个小问题。我们发现小问题和大问题在本质上是一致的,因此可以用递归的方式解决。

转载于:https://www.cnblogs.com/ovs98/p/9875626.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值