剑指 Offer 07. 重建二叉树之递归法

剑指 Offer 07. 重建二叉树

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

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

示例 1:

img

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]

这道题相信大部分童鞋们都做过,只不过一般是以选择或者填空的形式,突然要用一种语言来实现,可能有点懵。

首先可以回顾一下前序序列和中序序列是怎么形成的:

前序列:根节点–> 左子树 -->右子树

中序列:左子树 --> 根节点 --> 右子树

方法一:递归

所以我们先从先序序列中找到第一个元素preorder_root,就是整棵树的根元素.

然后在中序序列中定位到根元素的位置inorder_root,

这个位置的左边就是左子树(0 ~ inorder_root-1)

右边就是右子树(inorder_root+1 ~ n-1)。

我们可以通过中序序列中根元素的位置判断出左子树中元素的个数(size_left_subtree)

通过左子树元素的个数,我们可以在前序序列中定位到

左子树(preorder_root+1 ~ + preorder+size_left_subtree)

右子树(preorder+size_left_subtree~ n)

接下来我们要做的就是递归的建立根节点,并将每个节点与其左右子节点连接起来

这里需要注意的是,我们为了方便定位根元素在中序序列中的位置,我们为其创建一个HashMap,键为当前元素的值,值为当前元素的索引(因为题目说明了序列中不存在重复元素,此方法才可用)

代码如下:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    private HashMap<Integer,Integer> indexMap;
    public TreeNode buildTree(int[] preorder, int[] inorder) {
        int n = preorder.length;
      	//创建HashMap
        indexMap = new HashMap<Integer,Integer>();
      	//初始化HashMap
        for(int i=0; i<n; i++){
            indexMap.put(inorder[i], i);
        }
        return myBuildTree(preorder, inorder, 0, n-1, 0, n-1);
    }

    public TreeNode myBuildTree(int[] preorder, int[] inorder, int preorder_left, int preorder_right, int inorder_left, int inorder_right){
      	// 递归的边界条件
        if(preorder_left > preorder_right){return null;}
        // 前序列的第一个节点就是根节点
        int preorder_root = preorder_left;
      // 找到中序中对应的节点序号
        int inorder_root = indexMap.get(preorder[preorder_root]);
      // 建立根节点
        TreeNode root = new TreeNode(inorder[inorder_root]);
			// 得到左子树中的节点个数
        int size_left_subtree = inorder_root - inorder_left;
		  // 递归遍历左子树,并连接到根节点
      // 先序遍历的第preorder_left+1开始的 size_left_subtree 个节点,就是中序遍历的第0个到第inorder_root-1个节点
        root.left = myBuildTree(preorder, inorder, preorder_left+1, preorder_left+size_left_subtree, inorder_left, inorder_root-1);
      	//递归遍历右子树, 并连接到根节点
        // 先序遍历的preorder_left+1+size_left+subtree 到preorder_right 就是终须遍历的 inorder_root+1 到 inorder_right 的节点
        root.right = myBuildTree(preorder, inorder, preorder_left+size_left_subtree+1, preorder_right, inorder_root+1, inorder_right);
        return root;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值