从前序与中序遍历序列构造二叉树
难度:
标签:
题目描述
给定两个整数数组 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 <= preorder.length <= 3000
inorder.length == preorder.length
-3000 <= preorder[i], inorder[i] <= 3000
preorder
和inorder
均 无重复 元素inorder
均出现在preorder
preorder
保证 为二叉树的前序遍历序列inorder
保证 为二叉树的中序遍历序列
代码结果
运行时间: 224 ms, 内存: 19.1 MB
/*
* 解题思路:
* 1. 通过流处理查找根节点在中序遍历中的位置。
* 2. 使用流构建左右子树。
* 3. 递归构建整个树。
*/
import java.util.*;
import java.util.stream.*;
class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) { val = x; }
}
public class Solution {
public TreeNode buildTree(int[] preorder, int[] inorder) {
if (preorder.length == 0) return null;
int rootVal = preorder[0];
TreeNode root = new TreeNode(rootVal);
int inRootIndex = IntStream.range(0, inorder.length)
.filter(i -> inorder[i] == rootVal)
.findFirst()
.orElse(-1);
int[] leftInorder = Arrays.copyOfRange(inorder, 0, inRootIndex);
int[] rightInorder = Arrays.copyOfRange(inorder, inRootIndex + 1, inorder.length);
int[] leftPreorder = Arrays.stream(preorder)
.skip(1)
.limit(leftInorder.length)
.toArray();
int[] rightPreorder = Arrays.stream(preorder)
.skip(1 + leftInorder.length)
.toArray();
root.left = buildTree(leftPreorder, leftInorder);
root.right = buildTree(rightPreorder, rightInorder);
return root;
}
}
解释
方法:
该题解使用递归的方式,根据前序遍历和中序遍历的特点构建二叉树。首先,前序遍历的第一个元素一定是根节点。然后,在中序遍历中找到根节点的位置,根据根节点将中序遍历序列分为左右两部分,分别对应根节点的左右子树。接着,递归地对左右子树进行同样的处理,直到所有节点都被处理完。
时间复杂度:
O(n^2)
空间复杂度:
O(n)
代码细节讲解
🦆
在构建二叉树的过程中,如果节点值存在重复,当前的逻辑是否能正确处理?
▷🦆
递归构建子树时,如何确保preorder和inorder数组中的元素范围正确对应到子树的结构上?
▷🦆
在递归构建左右子树时,是否有可能通过改进算法减少重复的操作或优化递归过程?
▷相关问题
从中序与后序遍历序列构造二叉树
给定两个整数数组 inorder
和 postorder
,其中 inorder
是二叉树的中序遍历, postorder
是同一棵树的后序遍历,请你构造并返回这颗 二叉树 。
示例 1:

输入:inorder = [9,3,15,20,7], postorder = [9,15,7,20,3] 输出:[3,9,20,null,null,15,7]
示例 2:
输入:inorder = [-1], postorder = [-1] 输出:[-1]
提示:
1 <= inorder.length <= 3000
postorder.length == inorder.length
-3000 <= inorder[i], postorder[i] <= 3000
inorder
和postorder
都由 不同 的值组成postorder
中每一个值都在inorder
中inorder
保证是树的中序遍历postorder
保证是树的后序遍历