一、题目信息
- 题号:96
- 题目名称:Unique Binary Search Trees
- 题目叙述:
给定一个整数n,求由1到n为节点组成的不同二叉搜索树的数量。例如,当n = 3时,有 5 种不同的二叉搜索树。
二、模式识别(考点)
- 本题主要考查动态规划和二叉搜索树的性质。
- 考点在于根据二叉搜索树的特性,找出节点数量与不同二叉搜索树数量之间的递推关系,利用动态规划求解。
三、解题思路
- 思路一:动态规划
- 定义一个数组
dp,其中dp[i]表示i个节点可以组成的不同二叉搜索树的数量。 - 对于
dp[i],可以通过枚举根节点的位置j(从 1 到i),计算以j为根节点时的不同二叉搜索树数量。 - 以
j为根节点时,左子树的节点数为j - 1,右子树的节点数为i - j,根据乘法原理,以j为根节点的不同二叉搜索树数量为dp[j - 1] * dp[i - j]。 - 对
j从 1 到i进行枚举并累加结果得到dp[i]。
- 定义一个数组
四、C 语言代码实现
#include <stdio.h>
#include <stdlib.h>
// 函数 numTrees 用于计算由 1 到 n 为节点组成的不同二叉搜索树的数量
// @param n 表示二叉搜索树的节点数量
int numTrees(int n) {
if (n == 0) { // 当节点数为 0 时,只有一种情况(空树),返回 1
return 1;
}
int *dp = (int *)malloc((n + 1) * sizeof(int)); // 动态分配 dp 数组空间
dp[0] = 1; // 当节点数为 0 时,有一种情况(空树)
dp[1] = 1; // 当节点数为 1 时,有一种情况(一个节点的树)
for (int i = 2; i <= n; i++) { // 从节点数为 2 开始计算
dp[i] = 0; // 初始化 dp[i] 为 0
for (int j = 1; j <= i; j++) { // 枚举根节点位置
dp[i] += dp[j - 1] * dp[i - j]; // 计算以 j 为根节点时的不同二叉搜索树数量并累加
}
}
int result = dp[n]; // 存储最终结果
free(dp); // 释放 dp 数组的空间
return result;
}
int main() {
int n = 3;
int num = numTrees(n);
printf("The number of unique binary search trees with %d nodes is %d\n", n, num);
return 0;
}
代码解释:
numTrees函数:n:表示要计算的二叉搜索树的节点数量。- 首先处理
n = 0的情况,将dp[0]初始化为 1,因为空树是一种情况。 dp[1]初始化为 1,因为只有一个节点时只有一种二叉搜索树。dp数组用于存储中间结果,dp[i]表示i个节点可以组成的不同二叉搜索树的数量。- 外层
for循环从 2 到n遍历,计算dp[i]。 - 内层
for循环枚举根节点位置j,根据二叉搜索树的性质,左子树节点数为j - 1,右子树节点数为i - j,根据乘法原理,dp[j - 1] * dp[i - j]是以j为根节点的不同二叉搜索树数量,累加到dp[i]中。 - 最后将结果存储在
result中,并释放dp数组的内存。
设计模式:
- 这里使用了动态规划设计模式,通过存储中间结果
dp数组,避免了重复计算。
时间复杂度:O(n2)O(n^2)O(n2),外层循环 O(n),内层循环 O(n),整体为 O(n2)O(n^2)O(n2)。
空间复杂度:O(n)O(n)O(n),主要用于存储 dp 数组。
注意事项:
- 注意使用
malloc分配内存后,要使用free释放内存,避免内存泄漏。 - 对于较大的
n值,可能会有性能问题,因为时间复杂度是 O(n2)O(n^2)O(n2)。 - 确保
n的取值范围在合理范围内,避免超出int类型的表示范围,如果n很大,可考虑使用long long类型存储结果。
636

被折叠的 条评论
为什么被折叠?



