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

如题:

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

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

    3
   / \
  9  20
    /  \
   15   7

这道题明显是有套路的,如果你还不会,说明你是第一次遇到,还好现在遇到,省的笔试的时候现场尴尬。可以根据中序遍历和后序遍历得到的序列递归求解子树。首先,我们知道,后序遍历得到的序列从后往前依次是原二叉树的根节点,根节点右子树的根节点.....,右子树的左子树的根节点。如果不理解的话, 没关系,待会看幅图就理解了。其次呢,我们可以知道,中序遍历中,根节点的位置是在中间的。这样,第一次,我们从后序遍历中找到根节点的值val,然后在中序遍历中找到val所属下标i,这时候得到val的左子树范围为【0, i-1】,右子树范围为【i+1, end】。紧接着,我们继续在相应的子树范围内找根节点,谁的根节点,分别是右子树的根节点和左子树的根节点,找到后,和val组合即可。看下图:

从图中的后序遍历从后往前观察,20是根节点,18是20右子树的根节点,7是18右子树的根节点。8是18的左子树根节点。像这样每次递归的查找根节点,然后组合即可。初始遍历的时候,中序遍历范围为0~InEnd,找到第一次后,划分为左子树范围【0, i-1】,右子树范围【i+1, end】。每次遍历从后序遍历数列中取根节点前,先判断其实范围start是否大于end,如果是的话,说明已经到底了,这时候递归即可返回。这一点结合代码可以看出:

struct TreeNode *findSubTree(int* inorder, int* postorder, int *postEnd, int inStart, int inEnd)
{
    int val, i;
    struct TreeNode *root, *left, *right;
    
    //首先判断是否溢出了,溢出则返回。
    if (inStart > inEnd)
        return NULL;
    
    //取出子树根节点
    val = postorder[*postEnd];
    
    //指针指向下一个子树的根节点
    *postEnd = *postEnd - 1;
    
    //中序遍历查找根节点所在位置
    for (i = 0; i <= inEnd; i++)
        if (inorder[i] == val)
            break;
    
    //在划分后的范围内继续查找root的右子树和左子树,顺序不能搞错
    right = findSubTree(inorder, postorder, postEnd, i + 1, inEnd);
    left = findSubTree(inorder, postorder, postEnd, inStart, i - 1);
    
    //组合子树
    root = (struct TreeNode *)calloc(1, sizeof(struct TreeNode));
    root->val = val;
    root->left = left;
    root->right = right;
    return root;
}

struct TreeNode* buildTree(int* inorder, int inorderSize, int* postorder, int postorderSize){
    //第一个根节点位置
    int postEnd = postorderSize - 1;
    //第一次查找,中序范围为0~inorderSize - 1。
    return findSubTree(inorder, postorder, &postEnd, 0, inorderSize - 1);
}

参考资料:

1. 106. 从中序与后序遍历序列构造二叉树_哔哩哔哩 (゜-゜)つロ 干杯~-

     https://www.bilibili.com/video/av45393236

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

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

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值