根据一棵树的前序遍历与中序遍历构造二叉树
例如,给出
前序遍历 preorder = [3,9,20,15,7]
中序遍历 inorder = [9,3,15,20,7]返回如下的二叉树:
3
/ \
9 20
/ \
15 7来源:leetcode - 105
知识点:
- 前序遍历:[ 根节点,[ 左子树的前序遍历结果 ],[ 右子树的前序遍历结果 ]]
- 中序遍历:[[ 左子树的遍历结果 ],根节点,[ 右子树的中序遍历结果 ]]
简要思路:先根据前序遍历的概念,找出根节点,再在中序遍历中根据找到的根节点找出其左子树和右子树。
详细思路:前序遍历结果中第一个元素就是根节点,找出根节点后,再在中序遍历中找出根节点的位置,依靠根节点的位置将中序遍历划分开来,构造根节点,继续递归左子树和右子树进行构造,最终构造完整棵树,其中,为了减小时间复杂度,我们将中序遍历数组用 HashMap 存储起来,每次要在中序遍历结果中找根节点的位置时,只需要查找 HashMap 就可,降低了时间复杂度。
代码:
class Solution {
/**
* 时间复杂度:O(n),其中 n 是树中的节点个数
* 空间复杂度:O(n)
*/
private Map<Integer, Integer> indexMap;
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(preorder[preorder_root]);
// 得到左子树中的节点数目
int size_left_subtree = inorder_root - inorder_left;
// 递归的构造左子树,并连接到根节点
root.left = myBuildTree(preorder, inorder, preorder_left + 1, preorder_left + size_left_subtree, inorder_left, inorder_root - 1);
// 递归的构造右子树,并连接到根节点
root.right = myBuildTree(preorder, inorder, preorder_left + size_left_subtree + 1, preorder_right, inorder_root + 1, inorder_right);
return root;
}
public TreeNode buildTree(int[] preorder, int[] inorder) {
int n = preorder.length;
// 构造哈希映射,帮助我们快速定位根节点
indexMap = new HashMap<Integer, Integer>();
for (int i=0; i<n; i++){
indexMap.put(inorder[i], i);
}
return myBuildTree(preorder, inorder, 0, n-1, 0, n-1);
}
}
参考资料:官方题解