题目描述
输入某二叉树的前序遍历和中序遍历的结果,请构建该二叉树并返回其根节点。
假设输入的前序遍历和中序遍历的结果中都不含重复的数字。
-
二叉树遍历顺序:
前序遍历:根节点 -> 左节点 -> 右节点
中序遍历:左节点 -> 根节点 -> 右节点
-
所以二叉树遍历结果可以拆分为:
前序遍历:[根节点,[左子树遍历结果],[右子树遍历结果]]
中序遍历:[[左子树遍历结果],根节点,[右子树遍历结果]]
-
那么就可以从中序遍历知道左子树和右子树的节点数,也就知道了左子树和右子树在前序遍历中的边界
-
从中序遍历中拆分出左子树和右子树,再分别把他们当做一个新的二叉树,找出其根节点位置,依次递归下去
-
最后就可以构建出整个二叉树
示例
输入: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7]
输出: [3,9,20,null,null,15,7]
思路
Code
public class Solution {
//中序遍历每个结点对应的索引
HashMap<Integer, Integer> indexMap = new HashMap<>();
public TreeNode buildTree(int[] preorder, int[] inorder) {
for (int i = 0; i < inorder.length; i++) {
indexMap.put(inorder[i], i);
}
return buildRootNode(preorder, 0, 0, inorder.length - 1);
}
/**
* @param preorder 前序遍历
* @param root 根节点在前序遍历中索引
* @param left 结点在中序遍历的左边界
* @param right 结点在中序遍历的右边界
* @return 根节点
*/
private TreeNode buildRootNode(int[] preorder, int root, int left, int right) {
//左边界大于右边界, 递归结束
if (left > right) {
return null;
}
//根节点值
int val = preorder[root];
//创建根节点
TreeNode rootNode = new TreeNode(val);
//根节点在中序遍历的索引
int index = indexMap.get(val);
//递归左子树
//根节点索引: 左子树的根节点就在根节点右边, 所以为 root+1
//左边界: 左边界不变
//右边界: 中序遍历根节点两边分别为左子树和右子树, 所以左子树的右边界就是根节点左边一个, 即 index-1
rootNode.left = buildRootNode(preorder, root + 1, left, index - 1);
//递归右子树
//根节点索引: 因为前序遍历为 根节点+左子树+右子树, 所以右子树根节点坐标为 根节点坐标+左子树长度+1, 即 root+(index-left)+1
//左边界: 中序遍历根节点两边分别为左子树和右子树, 所以右子树的左边界就是根节点右边一个, 即 index+1
//右边界: 右边界不变
rootNode.right = buildRootNode(preorder, root + index - left + 1, index + 1, right);
//返回根节点
return rootNode;
}
}