105. Construct Binary Tree from Preorder and Inorder Traversal

描述

基于给出的前序遍历和中序遍历,构造出二叉树。

参考文献

Construct Binary Tree From Inorder and Preorder/Postorder Traversal

前序遍历和中序遍历的分析

重复值

在前序遍历和中序遍历中不会存在重复的item,因为如果存在重复的值,那么其表达的二叉树一定会产生歧义。
例如:

preorder = {8, 8}
inorder = {8, 8}

它的二叉树可以表述如下:

  8                 8
 /       或者         \   
8                      8

这两种形式都是合法的,所以在前序遍历和中序遍历中不会存在重复的item(当然还包括后序遍历啦)

解决办法

例如:

preorder = {7,10,4,3,1,2,8,11}
inorder = {4,10,3,1,7,11,8,2}

其二叉树为:

        _______7______
       /              \
    __10__          ___2
   /      \        /
   4       3      _8
            \    /
             1  11

我们可以看出:

  • 前序遍历中的第一个元素总会是有一个子树的root(例如:7)
  • 而在中序遍历中该root(例如:7)总会把左子树和右子树分开

结合这两点,我们可以很清楚的发现,这是一个递归的过程:
1. 首先取出preorder的第一个元素,构造为root(例如:7)
2. 在inorder中寻找root(例如:7)的index位置,则在index之前的元素表示是该二叉树的左子树(例如:{4, 10, 3, 1}),index之前的元素是该二叉树的右子树(例如: {11, 8, 2})
3. 把第2步找到的左子树和右子树分别在preorder中去对应,这样就形成了preorder1和preorder2,再把这两个子树分别从第1步开始循环递归。

具体代码如下:

class Solution {
    public TreeNode buildTree(int[] preorder, int[] inorder) {
        return buildTree2(0, 0,inorder.length-1,inorder,preorder);     
    }
    public TreeNode buildTree2(int inorder_head, int preorder_head,int inorder_tail,int[] inorder,int[] preorder) {
        if(inorder_tail-inorder_head<0 || preorder_head>preorder.length-1)
            return null;  
        TreeNode root= new TreeNode(preorder[preorder_head]);
        int index = 0; // Index of current root in inorder
        for (int i = inorder_head; i <= inorder_tail; i++) {
            if (inorder[i] == root.val) {
                index = i;
            }
        }
        root.left=buildTree2(inorder_head,preorder_head+1,index-1,inorder,preorder);
        root.right=buildTree2(index+1,preorder_head+index-inorder_head+1,inorder_tail,inorder,preorder);
        return root;
    } 
}

代码分析
  • 在每一次递归中要去inorder中寻找root,然后把它分为左右子树。
  • inorder_head表示目前子树的头索引,inorder_tail表示目前子树的尾索引
  • preorder_head指向的是当前root
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值