思路:动态规划
对于给定的n,如果我们枚举根节点的值为i,则其左子树的节点值为1,2,3,...,i-1,共有i-1个节点;右子树的节点值为i+1,i+2,...,n,共有n-i个节点。
假设左子树有x种不同的形态,右子树有y种不同的形态,则以i为根节点的二叉搜索树的总数为x*y。
因此,对于每个i,以i为根节点的二叉搜索树的总数为x[i]*y[i],而所有以1~n为根节点的二叉搜索树的总数即为它们的和。
我们可以定义一个数组dp,其中dp[i]表示由i个节点组成的不同二叉搜索树的个数。根据上述思路,我们可以得到如下状态转移方程:
其中,dp[j-1]表示左子树的不同形态数,dp[i-j]表示右子树的不同形态数,乘积表示以j为根节点的不同形态数。
初始状态dp[0]=1,因为当节点数为0时,只有一种形态,即空树。
最终结果为dp[n]。
时间复杂度:O(n^2)
空间复杂度:O(n)
class Solution {
public int numTrees(int n) {
int[] dp = new int[n+1];
dp[0] = 1;//0个根节点,只有一种情况,就是null空树
for (int i = 1; i <= n; i++) {//i为取不同的根节点
for (int j = 1; j <= i; j++) {
// dp[j-1]表示左子树的不同形态数
// dp[i-j]表示右子树的不同形态数
// 乘积表示以j为根节点的不同形态数。
dp[i] += dp[j-1] * dp[i-j];
}
}
return dp[n];
}
}
以上思路来源chat-GPT