【动态规划-6】96.不同的二叉搜索树

题目描述:

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

示例 1:

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

示例 2:

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

解题思路:

方法一:动态规划

核心思路:

状态定义:

dp[i] = 由 i 个节点组成的二叉搜索树的数量。

状态转移:

对于 i 个节点,枚举根节点:

  • 根节点左边有 j 个节点(构成左子树)

  • 根节点右边有 i - 1 - j 个节点(构成右子树)

复制代码
dp[i] = Σ dp[j] × dp[i-1-j],j 从 0 到 i-1

具体过程示例:

n = 3

复制代码
dp[0] = 1(空树)
dp[1] = 1(1个节点)
dp[2] = dp[0]*dp[1] + dp[1]*dp[0] = 1 + 1 = 2
dp[3] = dp[0]*dp[2] + dp[1]*dp[1] + dp[2]*dp[0] = 2 + 1 + 2 = 5 ✅

枚举根节点:

  • 根=1:左0个,右2个 → dp[0] * dp[2] = 2

  • 根=2:左1个,右1个 → dp[1] * dp[1] = 1

  • 根=3:左2个,右0个 → dp[2] * dp[0] = 2

总计:2 + 1 + 2 = 5 ✅

代码实现:

cpp 复制代码
class Solution {
public:
    int numTrees(int n) {
        vector<int> dp(n + 1, 0);
        dp[0] = 1;  // 空树
        dp[1] = 1;  // 1个节点
        
        for (int i = 2; i <= n; i++) {
            for (int j = 0; j < i; j++) {
                dp[i] += dp[j] * dp[i - 1 - j];
            }
        }
        
        return dp[n];
    }
};

复杂度分析:

维度 复杂度 说明
时间复杂度 O(n²) 双重循环
空间复杂度 O(n) dp 数组

方法二:卡特兰数

核心思路:

dp[n] 就是卡特兰数 C_n:

复制代码
C_n = C(2n, n) / (n + 1)

代码实现:

cpp 复制代码
class Solution {
public:
    int numTrees(int n) {
        long long result = 1;
        for (int i = 1; i <= n; i++) {
            result = result * (n + i) / i;
        }
        return result / (n + 1);
    }
};

更安全的写法:

cpp 复制代码
class Solution {
public:
    int numTrees(int n) {
        long long C = 1;
        for (int i = 0; i < n; i++) {
            C = C * 2 * (2 * i + 1) / (i + 2);
        }
        return (int)C;
    }
};

复杂度分析:

维度 复杂度 说明
时间复杂度 O(n) 一次循环
空间复杂度 O(1) 只用常数个变量

两种方法对比:

方法 时间复杂度 空间复杂度 推荐度
动态规划 O(n²) O(n) ⭐⭐⭐⭐⭐
卡特兰数 O(n) O(1) ⭐⭐⭐⭐

动态规划更通用(能处理变种),卡特兰数更快但需要知道公式。

关键细节:

1. 为什么 dp[0] = 1?

空树也算一种情况。当根节点的左子树或右子树为空时,需要 dp[0] = 1 来保证乘法正确。

2. 为什么是 dp[j] * dp[i-1-j]?

  • 左子树有 j 个节点,有 dp[j] 种结构

  • 右子树有 i-1-j 个节点,有 dp[i-1-j] 种结构

  • 左右子树独立,所以用乘法

3. 卡特兰数的其他应用

  • 括号匹配数

  • 出栈序列数

  • 凸多边形三角划分

  • 满二叉树计数

总结:

要点 说明
核心思想 枚举根节点,左右子树独立
状态转移 dp[i] = Σ dp[j] × dp[i-1-j]
时间复杂度 O(n²)
空间复杂度 O(n)
相关推荐
rou1 小时前
Attention(注意力机制)
算法
信奥卷王1 小时前
[GESP202609 六级] 数组划分
数据结构·算法
大鹏的NLP博客1 小时前
C++ 内存安全的未来:从 Safety Profiles 到 Safe C++
c++·内存安全
牧羊人.3332 小时前
动手学深度学习 07|Resnet网络与迁移学习
网络·人工智能·深度学习·神经网络·算法·cnn·迁移学习
程序员zgh2 小时前
C++ erase() 函数用法
c语言·开发语言·c++·学习
All for pursuit.2 小时前
【并查集-2】399.除法求值
数据结构·c++·算法·leetcode
迪丽热爱3 小时前
一、C语言概述与程序结构
c语言·开发语言·算法
码爸3 小时前
动态规划介绍
算法·动态规划
怪奇云呼军4 小时前
教育试听预约后没到课,闪电智能 Voice Agent 如何做分层回访?
人工智能·python·算法·云计算·音视频