我正在解决一个LeetCode问题。问题是:
给定
n
,可以生成多少结构上唯一的BST,用于存储1...n
的值?例如,对于n=3
,可以生成总共5
个唯一BST,如下所示:
1 3 3 2 1
\ / / / \ \
3 2 1 1 3 2
/ / \ \
2 1 2 3
最大的upvoted解决方案使用DP和以下递归公式:
G(n) = G(0) * G(n-1) + G(1) * G(n-2) + … + G(n-1) * G(0)
其中G(n)
表示可以为n
生成的唯一BST的数量。代码如下:
class Solution {
public:
int numTrees(int n) {
vector<int> G(n+1);
G[0]=G[1]=1;
for(int i=2; i<=n; i++)
for(int j=1; j<=i; j++)
G[i]+=G[j-1]*G[i-j];
return G[n];
}
};
虽然我或多或少了解发生了什么,但我并不理解为什么我们采用笛卡尔产品(而不是简单的添加,这更直观)。根据我的理解:
G[i] += G[j-1] * G[i-j];
应改为:
G[i] += G[j-1] + G[i-j]; //replaced '*' with a '+'
这是因为,我认为i
作为当前根的唯一BST的数量应该是其左右BST数量的总和(?)子树。我确实尝试了一些例子,但不知何故,数字在原始解决方案中神奇地成倍增加(*
),最终答案出现在G[n]
中。
有人可以提供使用笛卡尔积而不是求和的直观解释吗?
答案 0 :(得分:1)
您可以通过数学归纳法,然后将其应用于子问题以获得结果。或者只是检查小值,然后选择更高的值。
例如: -
No of nodes BST representation
1 --> [1]
2 --> [2] [1]
/ \
[1] [2]
3 --> [1]
\
[2]
\
[3]
[2]
/ \
[1] [3]
[3]
/
[2]
/
[1]
4 -->
[1]
/ \
NUM{} NUM of keys with 3 val NUM{2,3,4}
[2]
/ \
NUM{1} NUM{3,4}
[3]
/ \
NUM{1,2} NUM{4}
[4]
/ \
NUM{1,2,3} NUM{}
从第4个案例中,您可以清楚地了解到,我们必须简单地将每个树中的左右子树分组的可能方式的数量相乘。对于给定数量的值,我们必须添加它们。这就是使用笛卡儿产品的原因。
该产品基本上为我们提供了所有可能的订单。 例如:
G[i] += G[j-1] * G[i-j];
这里j-1
个节点在左边(我们可以假设 不失一般性)和i-j
个节点到右子树。和 现在你可以用G[j-1]
方式安排左子树了 以G[i-j]
方式使用右子树。现在想想你可以安排多少种方式 有这个左边的原始树和rigth子树?它会 乘。因为左右子树的每个组合都会给出 崛起为一种独特的树形象。
这也解释了为什么我们定义G[0]=1
,因为它符合我们在这里做事的方式。而且没有价值的安排的数量也是一种安排。所以它被认为是1.