leetcode 105. 从前序与中序遍历序列构造二叉树 c语言递归解法

如题:

根据一棵树的前序遍历与中序遍历构造二叉树。
注意:
你可以假设树中没有重复的元素。

例如,给出
前序遍历 preorder = [3,9,20,15,7]
中序遍历 inorder = [9,3,15,20,7]
返回如下的二叉树:

    3
   / \
  9  20
    /  \
   15   7

套路题,考察你有没有学习过这种题型。同样的问题还有知道中序与后序构造二叉树(leetcode 106)。我们知道,前序遍历所得序列从左至右依次是:根节点,跟左子树根节点.....右子树根节点。和后序正好相反,后序遍历所得序列从后往前依次是根节点,根右子树根节点...左子树根节点。因为题目保证没有重复数字,知道了根节点,就可以从中序遍历中找到对应下标i,根据中序遍历性质,i左边的数列表示左子树,i右边的数列表示右子树。这样,我们知道了根结点后,递归从中序数列中分别查找左子树的根结点和右子树根结点即可。

示例中给出的前序遍历数列为【3,9,20,15,7】,由下面的二叉树可以观察到,结点3为根结点,9为3的左子树根结点,20为3右子树根结点。15为20左子树根结点,7为20右子树根结点。递归查找顺序由此可得,先左子树后右子树。总的来说就是找根结点的过程。没有看懂的同学可以结合下面的代码看下:

//这道题和已知中序于后序遍历求二叉树类似,仅仅方向不同,递归求解即可
struct TreeNode *findSubRoot(int* preorder, int* inorder, int *preOrderEnd, int inStart, int inEnd)
{
    int i, val;
    struct TreeNode *root, *left, *right;
    
    //中序序列找不到,说明是一个空节点
    if (inStart > inEnd)
        return NULL;
    
    //从前序遍历中取出根节点的值
    val = preorder[*preOrderEnd];
    
    //指向下一个子树的根节点
    *preOrderEnd = *preOrderEnd + 1;
        
    //找到val节点的左子树和右子树范围
    for (i = 0; i <= inEnd; i++)
        if (inorder[i] == val)
            break;
    
    //找到val的左子树与右子树,顺序不能反,先左后右
    left = findSubRoot(preorder, inorder, preOrderEnd, inStart, i - 1);
    right = findSubRoot(preorder, inorder, preOrderEnd, i + 1, inEnd);
    
    //组合
    root = (struct TreeNode *)calloc(1, sizeof(struct TreeNode));
    root->val = val;
    root->left = left;
    root->right = right;
    return root;
}

struct TreeNode* buildTree(int* preorder, int preorderSize, int* inorder, int inorderSize){
    //前序遍历从前往后依次是根结点
    int preOrderEnd = 0;
    
    return findSubRoot(preorder, inorder, &preOrderEnd, 0, inorderSize - 1);
}

 

=============================================================================================

Linux应用程序、内核、驱动开发交流讨论群(745510310),感兴趣的同学可以加群讨论、交流、资料查找等,前进的道路上,你不是一个人奥^_^。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值