96. Unique Binary Search Trees

一、题目信息

  • 题号:96
  • 题目名称:Unique Binary Search Trees
  • 题目叙述
    给定一个整数 n,求由 1n 为节点组成的不同二叉搜索树的数量。例如,当 n = 3 时,有 5 种不同的二叉搜索树。

二、模式识别(考点)

  • 本题主要考查动态规划和二叉搜索树的性质。
  • 考点在于根据二叉搜索树的特性,找出节点数量与不同二叉搜索树数量之间的递推关系,利用动态规划求解。

三、解题思路

  • 思路一:动态规划
    1. 定义一个数组 dp,其中 dp[i] 表示 i 个节点可以组成的不同二叉搜索树的数量。
    2. 对于 dp[i],可以通过枚举根节点的位置 j(从 1 到 i),计算以 j 为根节点时的不同二叉搜索树数量。
    3. j 为根节点时,左子树的节点数为 j - 1,右子树的节点数为 i - j,根据乘法原理,以 j 为根节点的不同二叉搜索树数量为 dp[j - 1] * dp[i - j]
    4. 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 类型存储结果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

请向我看齐

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值