题目描述:LeetCode官网
思路:可能会很自然想到递归来写,但递归有很多重复计算,树的建立是一个递归过程,但同时也是将大问题转化成一个个子问题来解决的,可以考虑动态规划,就像递归建立二叉树一样,我们可以让任意一个结点当做根结点,这样每次的二叉树都是不一样的,至于每一个节点做根结点会产生有多少种树呢?假设n=3,当1为根结点时,2 3只能是它的右子树上的结点,左子树上就没有结点,而2 3的排列又由2 3哪一个先创建来决定,即每一个结点其实既是孩子结点又是根结点,而且子树的建立跟树的建立是相同的,故可以用动态规划来做。所以无论哪一个结点做根节点,产生的不同的二叉树的数目就是左子树的数目乘以右子树的数目(笛卡尔积),因为左子树和右子树是相互独立的。用g(i)表示第长度为 n 的序列能构成的不同二叉搜索树的个数,如果第i个数做根节点,它的左子树的就有i-1个数,这i-1个数能构成的不同二叉树的个数为g(i-1),同理右子树就有n-i个数,这n-i个数能构成的不同二叉树的个数为g(n-i)个,那么n个元素以任意一个元素为根节点能构成的不同二叉搜索树的个数g(i)=g(i-1)*g(n-i),则n个元素构成的不同二叉树个数就应该是每个元素构成不同二叉树的数目之和g(n)=g(1)*g(n-1)+g(2)*g(n-2)+...+g(n-1)g(1);
代码实现C++:
class Solution {
public:
int numTrees(int n) {
int g[30];
memset(g,0,sizeof(g));
g[0]=1;
g[1]=1;
for(int i=2;i<=n;i++){
for(int j=1;j<=i;j++){
g[i]+=g[j-1]*g[i-j];
}
}
return g[n];
}
};
刷题任务完成~~