【问题标题】:LeetCode: Unique Binary Search Trees CalculationLeetCode:唯一二叉搜索树计算
【发布时间】:2017-02-01 20:45:03
【问题描述】:

给定 n,有多少个结构唯一的 BST(二叉搜索树)存储值 1...n?

例如, 给定 n = 3,总共有 5 个唯一的 BST。

   1         3     3      2      1
    \       /     /      / \      \
     3     2     1      1   3      2
    /     /       \                 \
   2     1         2                 3

我有这个解决方案:

/**
 * Solution:
 * DP
 * a BST can be destruct to root, left subtree and right subtree.
 * if the root is fixed, every combination of unique left/right subtrees forms
 * a unique BST.
 * Let a[n] = number of unique BST's given values 1..n, then
 * a[n] = a[0] * a[n-1]     // put 1 at root, 2...n right
 *      + a[1] * a[n-2]     // put 2 at root, 1 left, 3...n right
 *      + ...
 *      + a[n-1] * a[0]     // put n at root, 1...n-1 left
 */
int numTrees(int n) {
    if (n < 0) return 0;
    vector<int> trees(n+1, 0);
    trees[0] = 1;

    for(int i = 1; i <= n; i++) 
        for (int j = 0; j < i; j++) 
            trees[i] += trees[j] * trees[i-j-1];

    return trees[n];
} 

因为这个答案是很久以前给出的,无法触及这个 'dragonmigo' 家伙。 这个解决方案被接受了,我的问题是:

在注释中,trees[0] 指的是 case 1。 (0+1 = 1)

如果是这样,trees[n-1] 应该引用 case 1...n 而不是 case 2...n。 (n-1+1=n)

我的想法错了吗?

附言我知道这实际上是一个加泰罗尼亚数,我知道使用推导公式解决它的算法。

【问题讨论】:

  • 你能解释清楚你想问什么吗?它是加泰罗尼亚数字。你想要它的证据还是别的什么?
  • 这不是我的意思。我的观点是注释中trees[n]的定义与代码中trees[n]的实际含义相冲突。
  • 就像这样 让 a[n] = 给定值的唯一 BST 的数量 1..n 那么 a[0] 应该代表什么?

标签: algorithm binary-search-tree catalan


【解决方案1】:

trees[n] 是恰好具有n 节点的树的数量。有 0 个节点的 1 棵树,因此 trees[0] == 1。对于给定的n &gt; 0,有一个根节点和两个子树,其总大小为:n-1

  • trees[n-1] 可能的树在左边,trees[0] 在右边
  • trees[n-2] 可能的树在左边,trees[1] 在右边
  • ...
  • trees[1] 可能的树在左边,trees[n-1-1] 在右边
  • trees[0] 可能的树在左边,trees[n-1] 在右边

当您在左侧有trees[k] 可能的树,在右侧有trees[l],它使trees[k]*trees[l] 成为可能的组合。这意味着:

trees[n] = trees[n-1]*trees[0]
         + trees[n-2]*trees[1]
         + ...
         + trees[1]*trees[n-2]
         + trees[0]*trees[n-1]

外循环计算所有trees[n]。内部循环使用上面显示的分解(以及n 之前的所有值的计算)计算其中的每一个。

【讨论】:

  • 似乎 trees[n-1] 可能的树在左边,而 trees[0] 在右边 将导致 n-1 + 0 = n-1 个节点,其他部分也是如此。该算法考虑了 n 个可能的条件,例如:(1 个节点,n-1 个节点),(2 个节点,n-2 个节点),...,(n-1 个节点,1 个节点),不是吗?跨度>
  • @Lancelod,否,因为:trees[0] 是 1 而不是 0,并且因为 k 左侧可能的树和 l 右侧可能的树导致 k*l 树而不是 k+l .原因是每一棵左边的树,在k 可能的树中,你在右边有l 可能的树。
  • 我明白你对 k x l 的看法。不解释让我感到困惑的地方是,代码作者写了 “Let a[n] = number of unique BST's given values 1..n”,这使得 a [0] 不清楚(1..0?)。是的,我的重点是如何描述 a[0] 的含义?你说这意味着 1 可能的树 并且你知道 case 0 节点 导致 1 可能的树 和 case 1 节点 也导致 1 种可能的树。这 1 棵可能的树 实际上来自什么?谢谢!
  • @Lancelod 我认为很明显只有 1 棵树由 1 个节点组成。棘手的情况是理解为什么有一棵树由 0 个节点组成。我没有一个很好的哲学理由。使用这个值很方便,因为它使其他计算正确且可能,就像我们定义0! = 1x^0 = 1 一样。如果你想一想,为什么 0 因素的乘积等于 1 ?唯一的原因是它使用唯一规则使其他计算正确。
  • 感谢0的耐心解释。:),但我明白为什么0节点可能是1个案例。似乎只有当我们将a[0]定义为'0 node'的case number,将a[n-1]定义为'n-1 nodes'的case number时,这个定义才不会与自身发生冲突。那么,如果是这样,案例“0 节点”和案例“n-1 节点”的组合如何成为所有“n 节点”案例的一部分? 如您所见,节点编号不兼容
猜你喜欢
  • 2022-01-24
  • 2021-06-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多