剑指 Offer 07. 重建二叉树
输入某二叉树的前序遍历和中序遍历的结果,请构建该二叉树并返回其根节点。
假设输入的前序遍历和中序遍历的结果中都不含重复的数字。
示例 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]
这道题相信大部分童鞋们都做过,只不过一般是以选择或者填空的形式,突然要用一种语言来实现,可能有点懵。
首先可以回顾一下前序序列和中序序列是怎么形成的:
前序列:根节点–> 左子树 -->右子树
中序列:左子树 --> 根节点 --> 右子树
方法一:递归
所以我们先从先序序列中找到第一个元素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;
}
}