给定一个整数 n,生成所有由 1 … n 为节点所组成的 二叉搜索树 。
示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| 输入:3 输出: [ [1,null,3,2], [3,2,null,1], [3,1,null,null,2], [2,1,3], [1,null,2,null,3] ] 解释: 以上的输出对应以下 5 种不同结构的二叉搜索树:
1 3 3 2 1 \ / / / \ \ 3 2 1 1 3 2 / / \ \ 2 1 2 3
|
提示:
我们枚举根结点的值为 i ,根据 BST 的性质,我们可以知道左子树的结点值集合为 [1 … i - 1],右子树的结点值集合为 [i + 1 … n]。我们可以使用递归来建立子树。
我们定义 generateTrees(start, end)
函数表示当前值的集合为 [start, end],返回序列 [start, end]生成的所有可行的 BST。我们在 [start, end] 中枚举根结点 i ,将序列分为 [start, i - 1] 和 [i + 1, end] 递归地调用 generateTrees 函数。我们获得了所有的可行的右子树,最后一步,我们从左右子树集合中任选两课拼接到根结点上。
当 start > end 时递归,BST 为空,返回空结点。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
|
class Solution { public List<TreeNode> generateTrees(int n) { if(n == 0){ return new LinkedList<TreeNode>(); } return generateTrees(1, n); }
List<TreeNode> generateTrees(int start, int end){ List<TreeNode> allTrees = new LinkedList<>(); if(start > end){ allTrees.add(null); return allTrees; } for(int i = start; i <= end; i++){ List<TreeNode> leftTrees = generateTrees(start, i - 1); List<TreeNode> rightTrees = generateTrees(i + 1, end); for(TreeNode left : leftTrees){ for(TreeNode right : rightTrees){ TreeNode curTree = new TreeNode(i); curTree.left = left; curTree.right = right; allTrees.add(curTree); } } } return allTrees; }
}
|
最后的结果存储了许多 BST 的根结点,我们以 n = 5, i = 3 为例来解释:
以 3 为根结点,左子树结点集合 为指向 1、2 的两个结点,右子树结点为指向 4、5 的两个结点,左右各取一个结点,新建一个根结点,生成 4 棵以 3 为根结点的 BST。
