前序遍历构造二叉搜索树
难度:
标签:
题目描述
给定一个整数数组,它表示BST(即 二叉搜索树 )的 先序遍历 ,构造树并返回其根。
保证 对于给定的测试用例,总是有可能找到具有给定需求的二叉搜索树。
二叉搜索树 是一棵二叉树,其中每个节点, Node.left
的任何后代的值 严格小于 Node.val
, Node.right
的任何后代的值 严格大于 Node.val
。
二叉树的 前序遍历 首先显示节点的值,然后遍历Node.left
,最后遍历Node.right
。
示例 1:
输入:preorder = [8,5,1,7,10,12] 输出:[8,5,10,1,7,null,12]
示例 2:
输入: preorder = [1,3] 输出: [1,null,3]
提示:
1 <= preorder.length <= 100
1 <= preorder[i] <= 10^8
preorder
中的值 互不相同
代码结果
运行时间: 32 ms, 内存: 14.9 MB
/*
* 思路:
* 1. 使用 Java Stream 构造二叉搜索树。
* 2. 前序遍历数组的第一个元素是树的根节点。
* 3. 使用流的分区功能将元素分为比根节点小的左子树和比根节点大的右子树。
* 4. 递归地构造左子树和右子树。
*/
import java.util.*;
import java.util.stream.*;
public class Solution {
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) { val = x; }
}
public TreeNode bstFromPreorder(int[] preorder) {
return constructBST(Arrays.stream(preorder).boxed().collect(Collectors.toList()));
}
private TreeNode constructBST(List<Integer> preorder) {
if (preorder.isEmpty()) return null;
TreeNode node = new TreeNode(preorder.get(0));
List<Integer> leftSubtree = preorder.stream().skip(1).filter(x -> x < node.val).collect(Collectors.toList());
List<Integer> rightSubtree = preorder.stream().skip(1).filter(x -> x > node.val).collect(Collectors.toList());
node.left = constructBST(leftSubtree);
node.right = constructBST(rightSubtree);
return node;
}
}
解释
方法:
首先,我们需要理解前序遍历的特点,即首个元素是树的根节点,其后是左子树的节点和右子树的节点。这个题解使用递归的方法,首先将根节点从前序遍历的首个元素建立,然后寻找左子树和右子树的分界点(即第一个大于根节点的元素),再对左右子树递归地进行同样的构建过程。这样,我们可以保证每次递归都正确地构建出左右子树。
时间复杂度:
O(n^2)
空间复杂度:
O(n)
代码细节讲解
🦆
在构造二叉搜索树的时候,题解中提到使用递归方法处理,这种递归处理在极端情况下是如何表现的?例如当输入是一个已经排序的数组。
▷🦆
题解中使用的辅助函数`helper`是否可以通过添加额外的参数或者使用其他数据结构来改善其效率?
▷🦆
在题解的递归构建过程中,如何保证每次递归调用都正确地构建出每个子树的根节点?
▷🦆
对于非常大的输入数组,题解中的方法可能会面临栈溢出的风险吗?如果是,有什么办法可以防止这种情况?
▷