不同的二叉搜索树
给你一个整数 n ,求恰由 n 个节点组成且节点值从 1 到 n 互不相同的 二叉搜索树 有多少种?返回满足题意的二叉搜索树的种数。
示例 1:
{:width=400}
输入:n = 3
输出:5
解题思路
首先二叉搜索树的定义:
左子树的所有节点值都小于根节点的值,右子树的所有节点值都大于根节点的值。
看示例 1 可以看出,n= 3 的 时候分别以 1,2,3 为根节点,它们的种类数量相加就是 1 到 n 为节点组成的二叉搜索树的个数为 dp[n],
我们就可以来推断了,比如
1 为根节点时:dp[3] = dp[0] * dp[2] ,左子树是没有的,右子树有两个。
2 为根节点时:dp[3] = dp[1] * dp[1] ,左右各一个。
3 为根节点时:dp[3] = dp[2] * dp[0] ,左子树有两个,右子树没有。
把它们相加起来就是 1-n 组成二叉搜索树的个数
dp[3] = dp[0] * dp[2] + dp[1] * dp[1] + dp[2] * dp[0]
那么就可以推断出它的
左子树节点个数为 i-1,
右子树节点个数为 n-i,
因此以 i 为根节点的二叉搜索树有 dp[i-1] * dp[n-i] 种情况。
代码
public int numTrees(int n) {
int[] dp = new int[n+1];
dp[0] = 1; // dp[0] 等于 0,也是说得通的,但是 我们的递推公式是乘法,所以不能是 0
for(int i = 1;i<=n;i++){
for(int j=1;j<=i;j++){
dp[i]+=dp[j-1]*dp[i-j];
}
}
return dp[n];
}
这里普及一下:为什么是左子树 * 右子树 ?
对于一颗 BST 而言,左子树的所有节点的值都小于根节点的值,右子树的所有节点的值都大于根节点的值。因此,左子树的节点数和右子树的节点数已经决定了整颗 BST 的形态,而不是左子树和右子树的种类数量之和。所以,左子树的种类数量乘右子树的种类数量才是以当前节点为根节点的 BST 的种类数量。