【问题标题】:Sum of roots of binary search trees of height ≤H with N nodesN个节点高度≤H的二叉搜索树的根和
【发布时间】:2015-08-10 04:02:33
【问题描述】:

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

例如,对于 N = 3,H = 3:有 2 棵以 1 为根的树,1 棵以 2 为根的树和 2 棵以 3 为根的树。

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

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

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

【问题讨论】:

    标签: math binary-search-tree


    【解决方案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;
     }
    }
    

    解释

    理解这个算法的关键是这样的:

    不管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.
    

    【讨论】:

      【解决方案2】:

      这里只是上述递归算法的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)。 是否可以进一步优化!!

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多