力扣第96题 不同的二叉搜索树 c++ 二叉搜索树 动态规划 + 数学思维

题目

96. 不同的二叉搜索树

中等

相关标签

二叉搜索树 数学 动态规划 二叉树

给你一个整数 n ,求恰由 n 个节点组成且节点值从 1n 互不相同的 二叉搜索树 有多少种?返回满足题意的二叉搜索树的种数。

示例 1:

复制代码
输入:n = 3
输出:5

示例 2:

复制代码
输入:n = 1
输出:1

提示:

  • 1 <= n <= 19

思路和解题方法 一 动态规划

  1. vector<int> dp(n + 1);:创建一个名为 dp 的整数向量,长度为 n+1。dp[i] 表示节点数量为 i 时的二叉搜索树数量。

  2. dp[0] = 1;:将 dp[0] 初始化为 1,因为当节点数量为 0 时,只有一种情况,即空树。

  3. for (int i = 1; i <= n; i++):遍历节点数量从 1 到 n 的所有情况。

  4. for (int j = 1; j <= i; j++):对于当前节点数量 i,遍历 j 从 1 到 i 的所有情况,表示以 j 作为根节点的情况。

  5. dp[i] += dp[j - 1] * dp[i - j];:计算以 j 作为根节点时,左子树和右子树的组合数,并将其累加到 dp[i] 中。dp[j - 1] 表示左子树的组合数,dp[i - j] 表示右子树的组合数。

  6. 最终返回 dp[n],即节点数量为 n 时的二叉搜索树数量。

复杂度

时间复杂度:

O(n^2)

时间复杂度为 O(n^2),因为有两个嵌套的循环。

空间复杂度

O(n)

空间复杂度为 O(n),因为使用了一个长度为 n+1 的向量来保存中间结果。

c++ 代码一

cpp 复制代码
class Solution {
public:
    int numTrees(int n) {
        // 创建一个长度为n+1的vector,用于存储不同数值的二叉搜索树的数量
        vector<int> dp(n + 1);
        // 初始化dp[0]为1,因为空二叉树也算一棵二叉树
        dp[0] = 1;
        // 循环计算dp数组中每个元素的值
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= i; j++) {
                // 根据公式计算dp[i]的值,即左子树数量×右子树数量之和
                dp[i] += dp[j - 1] * dp[i - j];
            }
        }
        // 返回dp[n],即n个节点的不同数值的二叉搜索树的数量
        return dp[n];
    }
};

思路和解题方法 二 数学思维

代码中,使用了一个变量C来表示二叉搜索树的数量。初始时,将C设置为1。

然后通过循环遍历i从0到n-1的所有情况,进行如下操作:

  1. 将C乘以2 * (2 * i + 1)。这一步是为了计算当前节点数量为i+1时,左子树的组合数。因为左子树的节点数量比根节点小,所以乘以2 * (2 * i + 1)可以得到左子树的组合数。

  2. 将C除以(i + 2)。这一步是为了计算右子树的组合数。右子树的节点数量比根节点大,所以除以(i + 2)可以得到右子树的组合数。

通过每次循环更新C的值,最终得到的C即为n个节点的二叉搜索树的数量。

这段代码利用了组合数的性质,将计算二叉搜索树数量的问题转化为了求解组合数的问题。

通过不断更新C的值,可以高效地计算出给定节点数量的二叉搜索树的数量。

需要注意的是,由于C的值可能非常大,所以在返回结果之前,将C强制转换为int类型。

复杂度

时间复杂度:

O(n)

时间复杂度分析: 代码中的循环从0到n-1遍历,每次循环都执行一些基本的数学运算,包括乘法、除法和加法。这些运算的时间复杂度都是常数级别的。因此,整个循环的时间复杂度为O(n)。

空间复杂度

O(1)

空间复杂度分析: 代码中只使用了一个变量C来存储二叉搜索树的数量,而且在整个过程中不需要额外的数据结构来存储中间结果。因此,空间复杂度为O(1),即常数级别的空间消耗。

c++ 代码二

cpp 复制代码
class Solution {
public:
    int numTrees(int n) {
        long long C = 1; // 初始化组合数C为1,用于存储二叉搜索树的数量
        for (int i = 0; i < n; ++i) { // 循环计算每个节点数量的二叉搜索树的数量
            C = C * 2 * (2 * i + 1) / (i + 2); // 计算组合数C的值
        }
        return (int)C; // 将组合数C强制转换为int类型并返回
    }
};

觉得有用的话可以点点赞,支持一下。

如果愿意的话关注一下。会对你有更多的帮助。

每天都会不定时更新哦 >人< 。

相关推荐
乐悠小码4 分钟前
数据结构------队列(Java语言描述)
java·开发语言·数据结构·链表·队列
2的n次方_8 分钟前
二维费用背包问题
java·算法·动态规划
ROC_bird..23 分钟前
STL - vector的使用和模拟实现
开发语言·c++
机器视觉知识推荐、就业指导23 分钟前
C++中的栈(Stack)和堆(Heap)
c++
simple_ssn36 分钟前
【C语言刷力扣】1502.判断能否形成等差数列
c语言·算法·leetcode
寂静山林1 小时前
UVa 11855 Buzzwords
算法
Curry_Math1 小时前
LeetCode 热题100之技巧关卡
算法·leetcode
ahadee1 小时前
蓝桥杯每日真题 - 第10天
c语言·vscode·算法·蓝桥杯
军训猫猫头2 小时前
35.矩阵格式的一到一百数字 C语言
c语言·算法
Mr_Xuhhh3 小时前
递归搜索与回溯算法
c语言·开发语言·c++·算法·github