重建二叉树

重建二叉树

输入某二叉树的前序遍历和中序遍历的结果,请构建该二叉树并返回其根节点。

假设输入的前序遍历和中序遍历的结果中都不含重复的数字

img

示例 1:

Input: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7]
Output: [3,9,20,null,null,15,7]

示例 2:

Input: preorder = [-1], inorder = [-1]
Output: [-1]

限制:

0 <= 节点个数 <= 5000

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/zhong-jian-er-cha-shu-lcof

考虑前序遍历和中序遍历的特点:

  • 前序遍历: 遍历结果的第一个节点一定是根节点
  • 中序遍历: 根节点的左边一定是左子树, 根节点的右边一定是右子树

基于二叉树前序遍历和后序遍历的这种特点:

我们很快就能找到根节点在中序遍历结果中的位置,并将中序遍历划分为 左子树——根节点——右子树这种结构

然后根据根节点的索引值可以确定左子树和右子树的长度,那么前序遍历就可以划分为根节点——左子树——右子树

对于左右子树,解决问题的方法没有变化,只是问题的规模变小了,显然我们可以用分治法解决这个问题。

递推参数root(根节点在前序遍历的索引值)left(子树的左边界在中序遍历的索引值)right (子树的右边界在中序遍历中的索引值)

结束条件left > right时,注意不能使用>=,left = right时,代表子树只有一个根节点

递推

  1. 建立根节点(值为该树前序遍历结果的第一个)

  2. 划分左右子树(需要查询根节点在中序遍历中的索引

    优化:一般情况下,使用一个for循环就可以找到根节点在中序遍历中的位置

    但是使用哈希表进行查询可以将该过程的时间复杂度从O(n)降至O(1)

  3. 开始递归,构建子树

!注意索引位置的确定

首先要确定是在先序遍历中的索引还是在中序遍历中的索引

对于 root left right三个参数

root要通过先序遍历的内容确定,因此要找到根节点在先序遍历中的索引

leftright是用来在中序遍历中划分子树,因此要找leftright在中序遍历中的索引值

根节点左边界右边界
左子树root+1lefti
右子树i-left+root+1i+1right

其中右子树的根节点可能不太好理解:

可以理解为:根节点(root)+ 左子树长度(i - left)+ 1

返回值: 递推中建立的根节点

复杂度分析:
时间复杂度 O(N)
空间复杂度 O(N)

代码

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    int[] preorder;
    HashMap<Integer, Integer> map = new HashMap<>();
    
    public TreeNode buildTree(int[] preorder, int[] inorder) {
        this.preorder = preorder;
        for(int i=0; i<inorder.length; i++){
            map.put(inorder[i],i);
        }
        return build(0,0,preorder.length-1);
    }

    public TreeNode build(int root, int left, int right){
        if(left > right){
            return null;
        }
        TreeNode node = new TreeNode(preorder[left]);
        int i = map.get(node.val);
        node.left = build(root+1,left,i-1);
        node.right = build(root+i-left+1, i+1, right);
        return node;
    }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Liwan95

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值