具有N个节点

时间:2015-08-09 15:37:59

标签: math binary-search-tree

考虑所有可以使用前N个自然数创建的高度≤H的二叉搜索树。找到这些二叉搜索树的根的总和。

例如,对于N = 3,H = 3:有2棵树,其中1作为根,1棵树,2作为根,2棵树,3作为根。

因此,Sum = 2 *(1)+ 1 *(2)+ 2 *(3)= 10

我试图通过以某种方式编写与f(n-1,h-1)和f(n-1,h)相关的函数f(n,h)来解决这个问题,但是无法找到解决方案。

注意:所有数字[1,N]必须存在于树中,高度应为≤H

2 个答案:

答案 0 :(得分:1)

好吧,让我们从基础开始。

可以使用以下算法非常容易地计算使用前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;
 }
}

<强>解释

理解这个算法的关键是:

无论不同的密钥是什么,BST的数量仅取决于不同密钥的数量

所以,这就是我们在递归中使用的。对于左子树,不同值的数量是root-1,对于右子树,不同值的数量是N-root。同样我们给每个键有机会成为root使用for循环。

现在,让我们处理高度H的约束。我假设高度是从根到叶子路径的边数。这也可以通过专注于上述算法来处理,技巧是:

我们不会调用高度&gt;的递归函数调用。 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;
 }
}

现在总和可以很容易地计算为

arr[0]*1 + arr[1]*2 + ..... arr[N-1]*N.

答案 1 :(得分:1)

这里只是上述递归算法的DP转换。

int bottom_up_specific_height(int n,int h){
 int i,j,l;
 for(l=0;l<=h;l++){
   dp[0][l]=1;
   dp[1][l]=1;
 } 
 int s=0;
 for(i=2;i<=n;i++){
   for(j=1;j<=i;j++){
     for(l=h;l>=0;l--){
       if(l==h)
         dp[i][l]=0;
       else  
         dp[i][l]+=(dp[j-1][l+1]*dp[i-j][l+1]);
       if(l==0 && i==n) 
         s+=(j)*(dp[j-1][l+1]*dp[i-j][l+1]);
     }

   }

 }  
  return s;
}

这里复杂度降低到O(h * n ^ 2)。 是否有可能进一步优化!!