纯净代码(c++)
class Solution {
public:
int numTrees(int n)
{
vector<int> S(n + 1, 0);
S[0] = 1;
S[1] = 1;
for (int i = 2; i <= n; ++i)
{
for (int j = 1; j <= i; ++j)
{
S[i] += S[j - 1] * S[i - j];
}
}
return S[n];
}
};
一些知识点:
1.二叉搜索树具有的属性:每个节点的值比它的左子树的所有节点的值都要大,但比它的右子树的所有节点的值都要小。注意这个定义排除了树中存在值相同的节点的可能性。
2.笛卡尔积又叫笛卡尔乘积,是笛卡尔提出来的。 简单的说是两个集合相乘的结果。 假设集合A={b, c},集合B={0, 1, 2},则两个集合的笛卡尔积为{(b, 0), (b, 1), (b, 2), (c, 0), (c, 1), (c, 2)}。而笛卡尔积在本题代表了一个根节点的左右子树是什么
由上图可知:
//F(i,n)=S(i−1)*S(n−i),当前节点有多少种可能与两个子树有关,而子树又与子树的子树有关
//S(i−1)为以i为根的左子树, S(n−i)为其右子树
//后一项的值需要前面的值来得出,如F(5)需要F(1,2,3,4)。
个人注释:
class Solution {
public:
int numTrees(int n)
{
vector<int> S(n + 1, 0);//S[n]表示当长度为n时有多少种二叉搜索树
S[0] = 1;//n不会为0,所以S[0] = 1表示的是空树,即nullptr
S[1] = 1;//当长度为1,以1作为根节点只有一种可能,所以S[1] = 1
for (int i = 2; i <= n; ++i)
//i表示长度,0,1对应的结果已经给出,从2开始,一步步推算到最大值
{
for (int j = 1; j <= i; ++j)
//内层循环表示长度为i,以不同数值为根(注意要有等于i的情况,要判断i作为根时的情况),判断i的二叉搜索树有多少种情况
//S[j - 1]为以j为根节点的左子树,S[i - j]为以j为根节点的到i的右子树,内层循环整体等于模拟正整数i从1到i分别为头结点时左右子树的情况
//F(i,n)=S(i−1)*S(n−i),当前节点有多少种可能与两个子树有关,而这两个子树之前已经推算出来并存储在S中
{
S[i] += S[j - 1] * S[i - j];
//长度为n的情况下二叉搜索树的个数为分别取不同值为根进行判断,将值累加。内层循环每循环一次S[i]就累加,直到当前长度所有情况计算完毕,得到长度为i时的二叉搜索树的数量。
}
}
return S[n];
}
};