二叉树题解

链接:https://www.nowcoder.com/questionTerminal/aaefe5896cce4204b276e213e725f3ea?answerType=1&f=discussion

来源:牛客网

小强现在有𝑛个节点,他想请你帮他计算出有多少种不同的二叉树满足节点个数为

𝑛且树的高度不超过𝑚的方案.因为答案很大,所以答案需要模上1e9+7后输出.

树的高度: 定义为所有叶子到根路径上节点个数的最大值.

这个问题是一个典型的动态规划问题,要求计算在给定节点数 ( n ) 和高度限制 ( m ) 的条件下,可以构造出多少种不同的二叉树。由于答案可能非常大,需要对结果取模 ( 10^9 + 7 )。

问题分析

  1. 定义状态:用 ( dp[i][j] ) 表示有 ( i ) 个节点且高度不超过 ( j ) 的二叉树的数量。
  2. 状态转移方程:对于每个节点数 ( i ),高度限制 ( j ),考虑根节点的左子树和右子树的划分。假设左子树有 ( k ) 个节点,那么右子树就有 ( i - 1 - k ) 个节点。左子树和右子树的高度限制为 ( j - 1 )(因为根节点占用一层高度)。因此,状态转移方程为: [ dp[i][j] = \sum_{k=0}^{i-1} dp[k][j-1] \times dp[i-1-k][j-1] ]
  3. 边界条件:( dp[0][j] = 1 ):空树的高度为 0,只有一种情况。( dp[i][0] = 0 )(对于 ( i > 0 )):非空树的高度不能为 0。
  4. 最终结果:( dp[n][m] ) 即为所求。

代码实现

以下是 Python 的实现代码:

mod = 1000000007

def count_trees(n, m):
    # 初始化 dp 数组
    dp = [[0] * (m + 1) for _ in range(n + 1)]
    
    # 空树的情况
    for j in range(m + 1):
        dp[0][j] = 1
    
    # 动态规划填表
    for i in range(1, n + 1):
        for j in range(1, m + 1):
            for k in range(i):
                dp[i][j] = (dp[i][j] + dp[k][j - 1] * dp[i - 1 - k][j - 1]) % mod
    
    return dp[n][m]

# 输入
n, m = map(int, input().split())
# 输出结果
print(count_trees(n, m))

代码解释

  1. 初始化:dp[0][j] = 1:空树的高度为 0,只有一种情况。dp[i][0] = 0(对于 ( i > 0 )):非空树的高度不能为 0。
  2. 动态规划填表:外层循环遍历节点数 ( i )。中层循环遍历高度限制 ( j )。内层循环遍历左子树的节点数 ( k ),计算右子树的节点数 ( i - 1 - k )。根据状态转移方程更新 ( dp[i][j] )。
  3. 取模操作:每次计算结果时对 ( 10^9 + 7 ) 取模,防止结果溢出。

示例

对于输入 ( n = 3 ),( m = 3 ),程序输出为 5,符合题目中的示例。

时间复杂度

  • 时间复杂度为 ( O(n \times m \times n) = O(n^2 \times m) )。
  • 空间复杂度为 ( O(n \times m) )。

这个解法能够高效地解决题目要求的问题。

全部评论
树形dp
点赞 回复 分享
发布于 07-09 12:18 北京

相关推荐

点赞 评论 收藏
分享
1️⃣第一轮1、逻辑题:8 5 3升的桶 8升水, 分成两个4升比较简单的逻辑题,也有通用题目 LeetCode 水壶问题2、算法题:一个字符串,找到第一个只出现一次的字符,n空间n时间,只能扫一次有原题:牛课题霸:第一个只出现一次的字符set或者更省内存的bitset3、算法题:字符串把多个连续空格合并成一个,输入是char*,要求原地空间4、算法题:一个整数数组,找最长的先增后降的序列基础题:牛客题霸:最长递增子序列先分别找最长递增和最长递减的,然后合并一下就好了5、c++基础,shared ptr的特点是什么,可以引用传参吗?c++11的智能指针,通过引用计数来管理,引用计数为0的时候释放内存,有效防止内存泄露的问题,每次拷贝引用计数都会+1,在传参时,不可以引用传参,原因是引用传参不会增加引用计数,在多线程或者闭包场景可能会导致引用计数混乱引发core或者内存泄露的问题6、项目:为什么设计神经网络解决问题,目前网络存在的问题是什么,后续可以怎么优化7、对于只有一个节点的二叉树,只会有一种结构,对于有两个节点的二叉树,会有2种可能的结构,对于有n个节点的二叉树,一共有几种可能的情况?当时直接就想列一下3,4,5个节点分别有多少种可能,然后看能不能找到规律,可是当去遍历4个节点时,发现遍历不住了,就放弃了。然后灵机一动,发现对于n个节点的二叉树,去掉根节点之后,会出现2个种情况。第一种一种是变成一颗n-1个节点的二叉树,这种情况存在两种可能。第二种另一种情况是,会变成一个a个节点的二叉树和一个b个节点的二叉树,a+b=n-1。这样很容易列出递推公式,问题就引刃而解了。2️⃣第二轮1、项目:为什么设计神经网络解决问题,目前网络存在的问题是什么2、二维有序数组 找target原题:牛课题霸:二维数组中的查找3、一个人打靶十次命中7次,命中率是70%,这个概率是怎么估算出来的面试官实际是想问极大似然估计,理解了题意之后就好回答了4、两瓶墨水,一红一黑,用小勺从红墨水瓶里舀一勺放入黑瓶,搅拌均匀,然后从黑瓶里舀一勺放入红瓶,这时红瓶里的红墨水多还是黑瓶里的黑墨水多?如果不搅匀呢?都是一样多,搅拌均匀的话可以很容易的写出公式。不搅匀的话,直接宏观来想,是守恒的,红墨水少了多少,就需要用多少黑墨水来填3️⃣第三轮1、算法题:顺时针打印二维数组原题 牛课题霸:顺时针打印矩阵关键考点是边界条件,奇数偶数两种情况如何简化代码,极限情况(例如1*1的矩阵)要确保能打印2、项目细节 出发点,为什么这么做,如何迭代的3、如果离开前一家公司的话,如果挽留你,什么地方最让你留恋,最可能不离职了
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务