好的,让我们从基础开始。
使用前 N 个自然数可以创建的 BST 的数量可以很容易地使用以下算法计算出来。
natural_number compute_no_of_BST(N)
{
if(N<=1)
return 1;
else
{
left=0,right=0,sum=0;
for(root = 1 to N)
{
left = compute_no_of_BST(root-1);
right = compute_no_of_BST(N-root);
sum = sum + (left*right);
}
return sum;
}
}
解释:
理解这个算法的关键是这样的:
不管distinct key是什么,BST的个数只取决于distinct key的个数
所以,这就是我们在递归中使用的。对于左子树,不同值的数量是 root-1,对于右子树,不同值的数量是 N-root。此外,我们给每个键作为root 使用 for 循环。
现在,让我们处理高度 H 的约束。我假设高度是从根到叶路径的边数。这也可以通过关注上述算法来处理,诀窍是:
我们不会调用递归函数调用高度 > H,为此我们必须跟踪从根开始遍历的边数,最初为 0。
这样就可以将范围缩小到新函数调用的样子。
natural_number compute_no_of_BST(N,H,0);
并且每次我们进行递归调用时,我们都会增加第三个变量以指示边遍历。
我们还将使用一个额外的数据结构,它是一个长度为 N 的数组,其中
arr[i] = number of BST with root i+1.
这是算法
natural_number compute_no_of_BST(N,H,l)
{
if(N<=1)
return 1;
else
{
left=0,right=0,sum=0;
for(root = 1 to N)
{
if(l+1<=H)
{
left = compute_no_of_BST(root-1,H,l+1);
right = compute_no_of_BST(N-root,H,l+1);
if(l==0)
arr[root-1] = (left*right);
sum = sum + (left*right);
}
}
return sum;
}
}
现在 sum 可以很容易地计算为
arr[0]*1 + arr[1]*2 + ..... arr[N-1]*N.