105.从前序与中序遍历序列构造二叉树
给定两个整数数组 preorder
和 inorder
,其中 preorder
是二叉树的先序遍历, inorder
是同一棵树的中序遍历,请构造二叉树并返回其根节点。
示例 1:
输入: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7]
输出: [3,9,20,null,null,15,7]
示例 2:
输入: preorder = [-1], inorder = [-1]
输出: [-1]
提示:
- 1 ≤ p r e o r d e r . l e n g t h ≤ 3000 1 \leq preorder.length \leq 3000 1≤preorder.length≤3000
inorder.length == preorder.length
- − 3000 ≤ p r e o r d e r [ i ] , i n o r d e r [ i ] ≤ 3000 -3000 \leq preorder[i], inorder[i] \leq 3000 −3000≤preorder[i],inorder[i]≤3000
preorder
和inorder
均 无重复 元素inorder
均出现在preorder
preorder
保证 为二叉树的前序遍历序列inorder
保证 为二叉树的中序遍历序列
解法一(递归+分治+Map)
思路分析:
- 参考从中序与后序遍历序列构造二叉树解法二,来解决该题
- 首先需要确定前序遍历为:中左右,中序遍历为:左中右;所以根据前序遍历来确定根节点,然后通过根节点对中序数组进行分割
- 可以建立中序数组的哈希表,来提高分割效率
- 因为前序遍历的根节点索引,是从前往后获得,所以需要先建立树的左子树,再建立树的右子树
- 对于递归的参数,将中序数组、前序数组、Map变量;赋值为全局变量后,参数只需包括中序数组的左右端指针
- 且递归函数返回类型为
TreeNode
实现代码如下:
class Solution {
int[] preorder; // 前序遍历数组
int[] inorder; // 中序遍历数组
Map<Integer, Integer> inMap; // 中序遍历数组 索引表
int preIndex; // 前序遍历数组 标识根节点值 索引
public TreeNode buildTree(int[] preorder, int[] inorder) {
if (preorder == null)
return null; // 边界条件 数组为空时 返回空树
// 对全局变量 进行赋值
this.preorder = preorder;
this.inorder = inorder;
inMap = new HashMap<>();
preIndex = 0;
// 构建中序遍历数组 索引表
for (int i = 0; i < inorder.length; i++) {
inMap.put(inorder[i], i);
}
return doBuildTree(0, inorder.length-1); // 递归构建二叉树
}
private TreeNode doBuildTree(int inLeft, int inRight) {
if (inLeft > inRight)
return null; // 若左端点 大于 右端点 则为空树
int value = preorder[preIndex]; // 获取 树 根节点值
TreeNode node = new TreeNode(value); // 构建树
int index = inMap.get(value); // 根据 根节点值 获取分割中序数组索引
preIndex ++; // 移动根节点索引
// 先构建左子树
node.left = doBuildTree(inLeft, index - 1);
// 再构建右子树
node.right = doBuildTree(index + 1, inRight);
return node; // 构建完成后 将树返回
}
}
提交结果如下:
解答成功:
执行耗时:1 ms,击败了99.35% 的Java用户
内存消耗:43.3 MB,击败了21.31% 的Java用户
复杂度分析:
- 时间复杂度: O ( n ) O(n) O(n)
- 空间复杂度: O ( n ) O(n) O(n)