给定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'的家伙。 这个解决方案被接受,我的问题是:
在评论中,树[0]引用案例 1 。 (0 + 1 = 1)
如果是这样,树[n-1]应该引用case 1 ... n 而不是 2 ... n 。第(n-1 + 1 = n)的
我的想法错了吗?
P.S。我知道这实际上是一个加泰罗尼亚数字,我知道算法使用演绎公式来解决它。
答案 0 :(得分:9)
trees[n]
是具有正好n
个节点的树的数量。有1个树有0个节点,因此trees[0] == 1
。对于给定的n > 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
之前的所有值的计算)计算每一个。