简单题目(只需要返回多少种):
给你一个整数 n
,求恰由 n
个节点组成且节点值从 1
到 n
互不相同的 二叉搜索树 有多少种?返回满足题意的二叉搜索树的种数。
示例:
输入:n = 3
输出:5
解题思路:
二叉搜索树关键的性质是根节点的值大于左子树所有节点的值,小于右子树所有节点的值,且左子树和右子树也同样为二叉搜索树。
本题我们使用动态规划算法来实现,把n个节点的问题,可以看作是更多个小的子问题来解
1.我们用G(n)来表示n个节点一共能组成多少个不同的二叉搜索树
2.fn[i]表示以i为根节点的二叉搜索树的个数
3.当i为根节点时,左子树的节点个数为i-1个,右子树的节点个数为n-i
4.那么fn[i]=G(i-1)*G(n-i)
源代码如下:
class Solution {
public:
//
int numTrees(int n) {
vector<int> fn(n+1,0);
fn[0]=1;//没有节点,只有一种
fn[1]=1;//只有一个节点,只能构成一种二叉搜索树
for(int i=2;i<=n;i++)
{
for(int j=1;j<=i;j++)
{
//为了节省代码,我们直接用fn[i]代替G(i)
fn[i]+=(fn[j-1]*fn[i-j]);
}
}
return fn[n];
}
};
升级题目:(需返回所有的二叉搜索树)
给你一个整数 n
,请你生成并返回所有由 n
个节点组成且节点值从 1
到 n
互不相同的不同 二叉搜索树 。可以按 任意顺序 返回答案。
输入:n = 3
输出:[[1,null,2,null,3],[1,null,3,2],[2,1,3],[3,1,null,null,2],[3,2,null,1]]
解题思路:
使用递归算法来实现本题
1.在(start,i-1)中递归地选择左子树的根节点,在(i+1,end)中递归地选择右子树的根节点
2.以当前i为根节点,选择合适的左子树和右子树,组合成一个符合条件的二叉搜索树
3.将当前这个二叉搜索树放进结果数组中即可
源代码如下:
class Solution {
public:
vector<TreeNode*> generateTrees(int n) {
if(n==0) return {};//没有节点 直接返回空数组
//起始从(1,n)中选择
return dfs(1,n);
}
private:
vector<TreeNode*> dfs(int start,int end)
{
//当start>end时,返回空
if(start>end) return {nullptr};
vector<TreeNode*> resTree;//结果数组
for(int i=start;i<=end;i++)
{
//构成左子树
vector<TreeNode*> leftTree=dfs(start,i-1);
//构成右子树
vector<TreeNode*> rightTree=dfs(i+1,end);
//组合二叉搜索树
for(auto& left:leftTree)
{
for(auto& right: rightTree)
{
//创建一个根节点为i的二叉树tempTree
TreeNode* tempTree=new TreeNode(i);
tempTree->left=left;
tempTree->right=right;
//将临时结果放入结果数组中
resTree.push_back(tempTree);
}
}
}
//返回结果
return resTree;
}
};