

一、题目描述
给定两个整数数组preorder(前序遍历)和inorder(中序遍历),构造二叉树并返回根节点。
前序:根 → 左 → 右;中序:左 → 根 → 右;题目保证节点值互不相同。
二、核心思路
- 前序数组第一个元素一定是当前子树的根节点。
- 在中序数组找到根节点下标:根左侧全部为左子树节点,右侧全部为右子树节点。
- 计算左子树节点数量
leftSize = rootIdx - inL,用这个数量切割前序数组,分出左、右子树对应的前序区间。 - 递归分别构建左子树、右子树;区间无效(
preL > preR)时递归终止,返回null。 - 哈希表优化:提前存储中序数组「值→下标」,查找根位置(O(1))。
三、完整 Java 代码
ini
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
Map<Integer, Integer> map;
public TreeNode buildTree(int[] preorder, int[] inorder) {
map = new HashMap<>();
for(int i = 0; i < inorder.length; i++){
map.put(inorder[i], i);
}
return build(preorder, 0, preorder.length-1, 0, inorder.length-1);
}
private TreeNode build(int[] pre, int preL, int preR, int inL, int inR){
if(preL > preR) return null;
int rootVal = pre[preL];
TreeNode root = new TreeNode(rootVal);
int rootIdx = map.get(rootVal);
int leftSize = rootIdx - inL;
root.left = build(pre, preL+1, preL+leftSize, inL, rootIdx-1);
root.right = build(pre, preL+leftSize+1, preR, rootIdx+1, inR);
return root;
}
}
四、实例推演表格
样例:preorder=[3,9,20,15,7],inorder=[9,3,15,20,7]
| 递归调用 | preL,preR | inL,inR | rootVal | rootIdx | leftSize | 动作 |
|---|---|---|---|---|---|---|
| 第一层 | 0,4 | 0,4 | 3 | 1 | 1 | 左子树 pre 1,1,右子树 pre 2,4 |
| 根 3 的左子树 | 1,1 | 0,0 | 9 | 0 | 0 | 左右子树均为 null |
| 根 3 的右子树 | 2,4 | 2,4 | 20 | 3 | 2 | 左子树 pre 3,3,右子树 pre 4,4 |
| 根 20 的左子树 | 3,3 | 2,2 | 15 | 2 | 0 | 左右子树均为 null |
| 根 20 的右子树 | 4,4 | 4,4 | 7 | 4 | 0 | 左右子树均为 null |
五、复杂度分析
- 时间复杂度:(O(n)),n 为节点数。哈希表预处理(O(n)),每个节点递归构建一次,哈希查找(O(1))。
- 空间复杂度:(O(n)),哈希表存储全部节点;递归栈最坏(O(n))(单链树),平衡二叉树(O(logn))。
六、易错点总结
inL不是固定等于 0,每次递归随当前子树区间动态改变;leftSize = rootIdx - inL,表示当前子树在中序区间内根左边节点数量。- 区间边界:左子树前序
[preL+1, preL+leftSize];右子树起点必须preL+leftSize+1,不要漏 + 1。 - 递归终止条件:
preL > preR,区间相等时还有一个节点,需要创建节点,不能直接返回 null。 - 哈希表可用前提:题目节点值不重复。
七、个人感悟
这道题核心是前序找根,中序划分左右。不需要切割数组,只用下标标记区间,节省数组拷贝开销;哈希表是重要优化,不使用哈希表时间复杂度退化为(O(n^2))。递归分治思想,把大问题拆成构造左子树、构造右子树两个子问题。