难度中等1188收藏分享切换为英文接收动态反馈
给你一个整数 n
,请你生成并返回所有由 n
个节点组成且节点值从 1
到 n
互不相同的不同 二叉搜索树 。可以按 任意顺序 返回答案。
示例 1:
输入:n = 3 输出:[[1,null,2,null,3],[1,null,3,2],[2,1,3],[3,1,null,null,2],[3,2,null,1]]
示例 2:
输入:n = 1 输出:[[1]]
提示:
1 <= n <= 8
算法 :二叉查找树
解题思路
这题需要构造出所有不同的二叉查找树。
由于二叉查找树的性质,对于一个二叉查找树的节点,它的左子树中所有节点的值都小于它的值,它的右子树中所有节点的值都大于它的值。而且二叉查找树的中序遍历是一个排好序的数组。
我们可以枚举根节点的所有可能的值。如果根节点的值等于ii,那么左子树的节点值在范围1,i−1内,右子树节点的值在范围i+1,n中。遍历左子树的所有情况和右子树的所有情况,就可以组合出当根节点的值等于ii时的所有情况。
根据以上的推导,我们可以发现这是一个明显的递归结构,左右子树也可以用这个递归结构构造。那么我们就可以用递归来解决这个问题。
代码思路
递归的步骤:
1、递归出口,如果start值大于end值,返回一个只含空节点的列表。
2、枚举根节点的值root_val,从start到end。
3、递归获得所有可能的左子树start, root_val - 1。
4、递归获得所有可能的右子树root_val + 1, end。
5、遍历左右子树的所有可能,组合成新的树,加入结果数组result中。
6、返回结果数组result。
复杂度分析
设二叉查找树的节点数为NN。 C(n)=(2n)!/(n!(n+1)!)为卡特兰数第n项的计算公式。 所有不同的节点数为NN的二叉查找树为对应的卡特兰数C(N)。
时间复杂度:O(N∗C(N))
由于有的子树会被重复计算,时间复杂度为O(N∗C(N))。
空间复杂度:O(N)
空间复杂度取决于树的最大深度,O(N)。
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public List<TreeNode> generateTrees(int n) {
return dfs(1,n);
}
public List<TreeNode> dfs(int start,int end) {
List<TreeNode> result = new ArrayList<TreeNode>();
if(start > end) {
result.add(null);
return result;
}
// 枚举根节点的值
for(int rootval = start; rootval <= end; rootval++) {
// 递归获得所有可能的左子树
List<TreeNode> leftTrees = dfs(start,rootval-1);
// 递归获得所有可能的右子树
List<TreeNode> rightTrees = dfs(rootval+1,end);
// 枚举每一种左右子树的组合,组成新的二叉树
for(int i = 0; i < leftTrees.size(); i++) {
TreeNode leftNode = leftTrees.get(i);
for(int j = 0; j < rightTrees.size(); j++) {
TreeNode rightNode = rightTrees.get(j);
TreeNode root = new TreeNode(rootval);
root.left = leftNode;
root.right = rightNode;
result.add(root);
}
}
}
return result;
}
}