【问题标题】:The number of binary search trees二叉搜索树的数量
【发布时间】:2018-09-06 06:11:28
【问题描述】:

具有 20 个节点且元素为 1,2,3,...,20 的二叉搜索树的数量是多少,使得树的根为 12,左子树的根为 7? 一)2634240 b) 1243561 c) 350016 d) 2642640

解释和答案会很有帮助。

我已经应用了加泰罗尼亚数字公式,但结果与选项不合适,所以这只是为了确定。

【问题讨论】:

  • 左子树的根是7开头还是左树本身是7且只有7
  • 你能展示你对加泰罗尼亚数公式的应用吗?那么也许我们可以指出你哪里出错了。顺便说一句,这可能更适合math.stackexchange.com,除非您希望通过实施某种蛮力搜索来解决这个问题。
  • 左子树的根为 7,并有其他元素作为其子树。
  • Cn= (2n)!/((n+1)!*n!) ;我用了这个公式
  • 我在每个节点上都有值,总共有 20 个节点,值为 12 的节点是根,值为 7 的节点是值为 12 的节点的左子树的根。

标签: algorithm data-structures tree


【解决方案1】:

使用Catalan numbers,计算具有n 节点的完整二叉树,答案将是d) 2642640 = 14 * 132 * 1430。这就是从我们每个未知子树扩展(子)树的可能性。

           12
          /  \
         7    (8 nodes)
        / \
(6 nodes) (4 nodes)


更新

正如 Mark Dickinson 在下面的 cmets 中所建议的,澄清一下:上图中和第一条语句中提到的“节点”是“内部”节点,我们正在以各种方式排列它们,而 nth加泰罗尼亚数字正在计算 具有n+1 叶节点的完整二叉树Binary trees with l leaf nodes have l - 1 internal nodes.

【讨论】:

  • Nitpick:完整的二叉树在这里不太合适;我们对一般二叉树感兴趣,因此可能值得解释为什么(例如)C_6 适合用于 6 节点树的数量。 (相比之下,具有 6 个 leaf 节点的完整二叉树的数量是 C_5,这不是您想要的,而具有 6 个 total 节点的完整二叉树的数量节点为零,因为任何完整的二叉树都有奇数个节点。)
  • @MarkDickinson 好点。但是,“完整的二叉树”在这里对我来说似乎很合适,语言是从维基百科中这个加泰罗尼亚数字应用程序的描述中借来的。我们忽略了叶子,只计算节点(顶点),这正是因为在“满二叉树”中,每个顶点(节点)都有“两个孩子或没有孩子”,但在我们的例子中,树并不满。例如,具有 4 个节点的树变体有 5 个叶子,这就是为什么 C_4 适合我们的“4 节点”子树。
  • 是的,完全正确。我不争辩 C_6 * C_4 * C_8 是正确的。我建议通过包含一些额外的解释来改进答案。我们确实想要“具有n 节点的完整二叉树”的数量,但在这种情况下,n 的相关值是 13、9 和 17,似乎值得解释这些值的来源从。或者,为了与 Wikipedia 兼容,更改为“具有 n 个 节点的完整二叉树”可能更清楚,然后解释为什么我们要使用 n=7n=5n=9 而不是n=6n=4n=8,这是您当前的答案隐含的建议。
  • @MarkDickinson 已编辑。如果您认为可以改进,请随时编辑。
【解决方案2】:
  • 这基本上是希望您计算特定数量节点可能的唯一 BST 数量。

  • 最终,最终结果将是这些数字的乘积。

  • 如果这是在考试中,那么您将不得不进行乘法运算。否则,您可以使用dynamic programming 以编程方式解决此问题。

代码:

class Solution {
        public int numTrees(int n) {
           if(n < 3) return n;
           int[] dp = new int[n+1];
           dp[0] = 1; // just initializing it as base case
           dp[1] = 1;// meaning, only 1 possibility for 1 node.
           dp[2] = 2;// meaning, only 2 possibilities for 2 nodes.

           for(int i=3;i<=n;++i){
               for(int j=1;j<=i;++j){
                   int nodes_on_left_of_j  = j - 1;
                   int nodes_on_right_of_j = i - j;
                   dp[i] += dp[nodes_on_left_of_j] * dp[nodes_on_right_of_j]; // so multiply left side possibilites with right side possibilites for a particular root node.
               }
           }

           return dp[n];
        }
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-08
    • 1970-01-01
    • 1970-01-01
    • 2010-10-26
    • 1970-01-01
    相关资源
    最近更新 更多