剑指offer 07 重建二叉树

输入某二叉树的前序遍历和中序遍历的结果,请重建该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。

例如,给出

前序遍历 preorder = [3,9,20,15,7]
中序遍历 inorder = [9,3,15,20,7]

返回如下的二叉树:

    3
  /   \
  9    20
      /  \
     15   7

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/zhong-jian-er-cha-shu-lcof
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

题目难度中等。

首先需要二叉树的基本基本知识,前序、中序、后序 三种遍历顺序

即使掌握了三种遍历顺序,第一次拿到题,还是感觉一头雾水,没法下手。

需要仔细观察前序和中序的规律

很明显可以看出根节点在两个序列中的位置。

但仅仅凭借这个信息还是很难重构出二叉树的

还需要注意二叉树的两个特点:
1:中序遍历访问顺序:左子树的所有内容->跟节点->右子树
2:前序遍历的访问顺序:根节点->左子树->右子树

我们可以推断得到下图的规律,那么还是会有疑问,即使我知道了根节点以及左右子树的节点,那有怎么重建二叉树呢?

  3         9       20     15     7
根节点     左子树    右子树
  9         3       15     20     7
左子树     根节点    右子树

我们先简化问题,如果二叉树是一个最简单的二叉树,只有一个根节点,一个左子树,一个右子树,那么,我们是不是就可以根据

前文总结的两个特点完成重建了。

到这里,有经验的同学就很容易想到递归了,一开始学习递归感觉很复杂,想不明白,但是,其实你只需要想清楚一个最小的处理单元的逻辑结构就够了。

剩下的细节问题还是看代码吧

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */

struct TreeNode* buildTreeCore(int *startPreorder,int *endPreorder,
                        int *startInorder, int *endInorder){
        int root_value = *startPreorder;
        struct TreeNode* root = (struct TreeNode*)malloc(sizeof(struct TreeNode));
        root->val = root_value;
        root->left = root->right = NULL;
        if(startPreorder == endPreorder && startInorder == endInorder 
           && *startInorder == *endInorder)
           return root;
        //find pos at inorder
        int *root_node = startInorder;
        while(*root_node != root_value){
             root_node++;
        }
        //cal left tree length and right tree length              
        int left_length = root_node - startInorder;
        int *leftPreorder_end = startPreorder + left_length; 
        
        //make sure left and right tree haven
        if(left_length >0)
            root->left = buildTreeCore(startPreorder+1,leftPreorder_end,
                                        startInorder,root_node-1);
        if(root_node != endInorder)
            root->right = buildTreeCore(leftPreorder_end+1,endPreorder,
                                        root_node+1,endInorder);
        return root;
}


struct TreeNode* buildTree(int* preorder, int preorderSize, int* inorder, int inorderSize){
    if ( NULL == preorder || NULL == inorder || preorderSize <= 0 
        || inorderSize <=0 || preorderSize!= inorderSize)
        return NULL;
    return buildTreeCore(preorder,preorder + preorderSize -1,
                         inorder, inorder + inorderSize - 1);
}

需要注意的是,写代码一定要严谨,该加上的判断一定要加上,特别是对于递归程序而言,如果终止条件不对,很容易陷入死循环,导致栈溢出

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值