输入某二叉树的前序遍历和中序遍历的结果,请构建该二叉树并返回其根节点。
假设输入的前序遍历和中序遍历的结果中都不含重复的数字。
示例 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
解题思路:
通过以上三步,可确定 三个节点 :1.树的根节点、2.左子树根节点、3.右子树根节点。
根据「分治算法」思想,对于树的左、右子树,仍可复用以上方法划分子树的左右子树。
分治算法解析:
复杂度分析:
代码:
注意:本文方法只适用于 “无重复节点值” 的二叉树。
class Solution {
int[] preorder;
HashMap<Integer, Integer> inorderIndexMap = new HashMap<>();
public TreeNode buildTree(int[] preorder, int[] inorder) {
this.preorder = preorder;
for (int i = 0; i < inorder.length; i++) {
inorderIndexMap.put(inorder[i], i);
}
return recur(0, 0, inorder.length - 1);
}
public TreeNode recur(int rootIndexInPreorder, int leftIndexInInorder, int rightIndexInInorder) {
// 递归终止
if (leftIndexInInorder > rightIndexInInorder) {
return null;
}
// 建立根节点
TreeNode rootTreeNode = new TreeNode(preorder[rootIndexInPreorder]);
// 划分根节点、左子树、右子树
int rootIndexInInorder = inorderIndexMap.get(rootTreeNode.val);
// 开启左子树递归
rootTreeNode.left = recur(rootIndexInPreorder + 1, leftIndexInInorder,
rootIndexInInorder - 1);
// 开启右子树递归
rootTreeNode.right = recur(rootIndexInInorder - leftIndexInInorder +
1 + rootIndexInPreorder, rootIndexInInorder + 1, rightIndexInInorder);
// 回溯返回根节点
return rootTreeNode;
}
}