96. 不同的二叉搜索树
给你一个整数 n ,求恰由 n 个节点组成且节点值从 1 到 n 互不相同的 二叉搜索树 有多少种?返回满足题意的二叉搜索树的种数。
示例 1:
输入:n = 3
输出:5
示例 2:
输入:n = 1
输出:1
提示:
1 <= n <= 19
思路
我们可以把n = 1 2 3 这三种情况都列出来,然后我们可以发现:
n = 1时,只有一个结点,值为1,也只能组成一种二叉搜索树。
n = 2时,1 2 可以1 为节点,也可以2为根节点,所以是两种情况。
n = 3时,也就是上图中的这一种情况,共五种情况,可以分成三大类:
- 1为根节点:剩下的都比1大,所以左子树有 1 - 1 = 0个结点,右子树有3 - 1 = 2个结点,那么情况又变成了右子树两个结点,左子树零个结点。所以此时次数 = 左子树0个结点的种类数 * 右子树2个结点的种类数
- 2为根节点:左子树 2 - 1 = 1个结点,右子树 3 - 2 = 1个结点,所以此时次数 = 左子树一个结点 * 右子树一个结点
- 3为根节点:左子树 3 - 1 = 2个结点,右子树 3 - 3 = 0个结点,所以此时次数 = 左子树两个结点 * 右子树一个结点
而我们也可以知道,无论左子树还是右子树对应结点数的种类数就等于dp[i]的值。
所以dp[3] = dp[2] * dp[0] + dp[1] * dp[1] + dp[0] * dp[2];
对于第 i 个结点,要考虑从 1 到 i 作为根节点的情况,所以需要累加
一共是 i 个结点,对于根节点 j ,此时,左子树有 j - 1 个结点,右子树有 i - j 个结点
代码
class Solution {
public:
int numTrees(int n) {
int dp[n + 1];
for (int i = 0; i <= n; i++) dp[i] = 0;
dp[0] = 1;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= i; j++) {
dp[i] += dp[i - j] * dp[j - 1];
}
}
return dp[n];
}
};
/*
//对于第i个节点,需要考虑1作为根节点直到i作为根节点的情况,所以需要累加
//一共i个节点,对于根节点j时,左子树的节点个数为j-1,右子树的节点个数为i-j
*/
/*
元素1为头结点搜索树的数量 = 右子树有2个元素的搜索树数量 * 左子树有0个元素的搜索树数量
元素2为头结点搜索树的数量 = 右子树有1个元素的搜索树数量 * 左子树有1个元素的搜索树数量
元素3为头结点搜索树的数量 = 右子树有0个元素的搜索树数量 * 左子树有2个元素的搜索树数量
有2个元素的搜索树数量就是dp[2]。
有1个元素的搜索树数量就是dp[1]。
有0个元素的搜索树数量就是dp[0]。
所以dp[3] = dp[2] * dp[0] + dp[1] * dp[1] + dp[0] * dp[2]
*/