题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
解题思路:递归
首先需要明白什么是二叉搜索树,二叉搜索树又叫二叉排序树,二叉查找树,它是一种对排序和查找都很有用的特殊二叉树。
二叉搜索树的定义:
二叉搜索树或者是一颗空树,或者是具有如下性质的二叉树:
- 若它的左子树不空,则左子树上所有节点的值均小于它的根节点的值
- 若它的右子树不空,则右子树上所有节点的值均大于它的根节点的值
- 它的左、右子树也分别为二叉搜索树。
二叉搜索树是递归定义的,所以此题可以使用递归进行构造所有的二叉搜索树,具体算法如下:
- 对与当前的二叉搜索树的根节点的值可以从1~n之间任意选择一个,一旦根节点的值确定,那么左子树中所有节点值的范围和右子树所有节点值的范围就确定了,比如根节点为 i ,则左子树所有节点值得大小在 1~i-1之间,右子树所有节点值得大小在 i+1~n之间。
- 而左子树和右子树根节点得值确定后,又可以进一步确定其左子树和右子树节点值得范围。
递归函数实现如下:
- 递归函数定义:List<TreeNode> generateTrees(int left,int right):表示节点值在[left , right]之间时,返回可以生成地所有不同地二叉搜索树。
- 递归终止条件:如果left > right:显然返回一颗空树
- 否则:
- result保存[left,right]生成的所有二叉搜索树
- 枚举left到right之间的值 i :
- 将 i 作为当前二叉搜索树的根节点的值
- 那么左子树所有节点值的范围为 [left , i-1 ],这些节点可以生成的所有左子树为:leftTrees = gengerateTrees(left,i-1)
- 右子树所有节点值的范围为[i+1 , right],这些节点可以生成的所有右子树为:rightTrees = generateTress(i+1 ,right)
- 对leftTrees和rightTrees分别进行枚举:
- 生成根节点
- 从leftTrees和rightTrees中选择一个节点作为根节点的左子树和右子树
- 将根节点加入结果集result中
- 返回result
AC代码:
/**
* 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 generateTrees(1,n);
}
public List<TreeNode> generateTrees(int left ,int right){
List<TreeNode> result = new ArrayList<>();
if (left>right){
//不满足,生成空树
result.add(null);
return result;
}
for (int i =left;i<=right;i++){
List<TreeNode> leftTrees= generateTrees(left,i-1);
List<TreeNode> rightTrees= generateTrees(i+1,right);
for (TreeNode leftTree : leftTrees) {
for (TreeNode rightTree : rightTrees) {
//因为Java对象是值引用,所以在这里每次都重新生成一个根节点
TreeNode root=new TreeNode(i);
root.left=leftTree;
root.right=rightTree;
result.add(root);
}
}
}
return result;
}
}