105. 从前序与中序遍历序列构造二叉树

根据一棵树的前序遍历与中序遍历构造二叉树。

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

注意:
你可以假设树中没有重复的元素。

例如,给出

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

    3
   / \
  9  20
    /  \
   15   7

中序遍历与前序遍历在一起可以唯一确定一颗二叉树
前序遍历中 第一个节点一定是根节点 在中序遍历中找到他的位置i ,在i前面的都是左子树 ,后面的都是右子树
关键就是找前序遍历中 左子树与右子树根节点的位置。
以给出的例子示意 ,9 就是其左子树 但是 15,20,7 是右子树 如何找到右子树在前序遍历 中开始的位置?
通过左子树的长度来判断! 可知左子树长度是1 所以 右子树的在前序遍历中开始的位置就是根节点的位置加1(左子树的长度)+1
这样就可以找到左右子树的自己的起始根节点 接着递归左右子树
因此在递归时可以采用 起始点作为标记 先序遍历 :p_start ,p_end 中序 i_start, i_end;
当P_start=p_end 说明当前序列为空 ,返回null 不为空说明有子树 选取根节点 in[i_root_index ]= pr[p_start]
定义左子树长度leftNum 分割 两个序列 前序与中序都将其分为 左子树与右子树 两个部分

 [左] pr:p_start= p_start ,p_end = p_start+leftNum+1 [右]p_start=p_start+leftNum+1  ,p_end=p_end;
 [左] in: i_start= i_start,i_end=i_root_index;        [右]i_start=i_root_index+1; i_end=i_end;
class Solution {
        
public TreeNode buildTree(int[] preorder, int[] inorder) {
    return buildTreeHelper(preorder, 0, preorder.length, inorder, 0, inorder.length);
    }

private TreeNode buildTreeHelper(int[] preorder, int p_start, int p_end, int[] inorder, int i_start, int i_end) {
    // preorder 为空,直接返回 null
    if (p_start == p_end) {
        return null;
    }
    //在前序遍历中找到根节点 
    int root_val = preorder[p_start];
    //Node建立
    TreeNode root = new TreeNode(root_val);
    //在中序遍历中找到根节点的位置
    int i_root_index = 0;
    for (int i = i_start; i < i_end; i++) {
        if (root_val == inorder[i]) {
            i_root_index = i;
            break;
        }
    }

    //计算左子树的长度 
    int leftNum = i_root_index - i_start;
    //递归的构造左子树  前序序列开始为 : p_start+1  结束为 :加入左子树的长度   中序序列为: 开始到根节点的位置之前
    root.left = buildTreeHelper(preorder, p_start + 1, p_start + leftNum + 1, inorder, i_start, i_root_index);
    //递归的构造右子树     中序:开始节点为:当前找到的根节点的位置 结束 i——end
    root.right = buildTreeHelper(preorder, p_start + leftNum + 1, p_end, inorder, i_root_index + 1, i_end);
    return root;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值