二叉搜索树序列
难度:
标签:
题目描述
A binary search tree was created by traversing through an array from left to right and inserting each element. Given a binary search tree with distinct elements, print all possible arrays that could have led to this tree.
Example:
Given the following tree:
2 / \ 1 3
Output:
[ [2,1,3], [2,3,1] ]
代码结果
运行时间: 30 ms, 内存: 17.1 MB
/*
* 思路:
* 使用Java Stream API来生成所有可能的数组。
* 和传统方法类似,我们通过递归来生成左右子树的所有可能数组,然后使用Stream的方式进行组合。
*/
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class SolutionStream {
public List<List<Integer>> BSTSequences(TreeNode root) {
if (root == null) {
return Stream.of(new ArrayList<Integer>()).collect(Collectors.toList());
}
List<Integer> prefix = new LinkedList<>();
prefix.add(root.val);
List<List<Integer>> leftSeq = BSTSequences(root.left);
List<List<Integer>> rightSeq = BSTSequences(root.right);
return leftSeq.stream().flatMap(left -> rightSeq.stream().map(right -> {
List<List<Integer>> results = new ArrayList<>();
weaveLists(left, right, prefix, results);
return results;
})).flatMap(List::stream).collect(Collectors.toList());
}
private void weaveLists(List<Integer> first, List<Integer> second, List<Integer> prefix, List<List<Integer>> results) {
if (first.isEmpty() || second.isEmpty()) {
List<Integer> result = new LinkedList<>(prefix);
result.addAll(first);
result.addAll(second);
results.add(result);
return;
}
int headFirst = first.remove(0);
prefix.add(headFirst);
weaveLists(first, second, prefix, results);
prefix.remove(prefix.size() - 1);
first.add(0, headFirst);
int headSecond = second.remove(0);
prefix.add(headSecond);
weaveLists(first, second, prefix, results);
prefix.remove(prefix.size() - 1);
second.add(0, headSecond);
}
}
class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) { val = x; }
}
解释
方法:
这道题目要求找到所有可能的数组序列,这些序列能够通过从左到右的插入操作重建给定的二叉搜索树(BST)。解题关键是理解每个节点必须在它的所有子孙节点之前出现。解决这个问题的方法是使用回溯法来模拟这个过程。算法使用一个队列来存储当前可用于插入到序列中的节点,这些节点是已经在序列中的节点的直接子节点。回溯过程中,从队列中选择一个节点,将其添加到当前路径,然后将其子节点添加到队列中,继续递归。每次递归调用后,需要将路径和队列状态回溯到之前的状态,以便尝试其他的选择。
时间复杂度:
O(n!)
空间复杂度:
O(n)
代码细节讲解
🦆
为什么选择使用回溯法来解决这个问题,有没有其他可能的算法可以应用?
▷🦆
在回溯过程中,如何保证每个节点在它的所有子孙节点之前出现在序列中?
▷🦆
在算法中,你提到了使用队列来维护当前可插入的节点,为什么选择使用队列而不是其他数据结构如栈或优先队列?
▷