青训营X豆包MarsCode 实践记录AI助力 小M的好二叉树 | 豆包MarsCode AI 刷题

15 阅读3分钟

问题描述

小M定义了一种特殊的二叉树,称之为“好二叉树”。当且仅当这个二叉树中的所有节点的孩子数量为偶数(即每个节点要么没有孩子,要么有两个孩子),该二叉树才被称为好二叉树。

现在,小M想知道,给定 n 个节点,可以构成多少种不同形态的好二叉树?答案需要对 10^9 + 7 取模。


测试样例

样例1:

输入:n = 5 输出:2

样例2:

输入:n = 7 输出:5

样例3:

输入:n = 9 输出:14

问题分析与思考

这个问题是一个经典的 组合数学问题,涉及到如何在给定的 n 个节点中构造符合特定条件的二叉树。问题中的二叉树要求每个节点的孩子数量是偶数,要么没有孩子(叶子节点),要么有两个孩子。

问题分析

我们可以通过 动态规划 来解决这个问题。我们的问题可以转化为以下几个部分:

  1. 二叉树的节点构成

    • 每个节点要么没有孩子,要么有两个孩子。
    • 因此,我们可以将一个节点视作一个根节点,它可以有两个子树。假设一个子树有 i 个节点,另一个子树有 n-1-i 个节点。由于每个子树必须也是一个 "好二叉树",所以我们递归地求解这个问题。
  2. 递推关系

    • 对于一个给定的节点数 n,我们可以将根节点拆分成左右两个子树,假设左子树包含 i 个节点,右子树包含 n-1-i 个节点,其中 i 是偶数。这样可以确保每个节点的孩子数量是偶数。

    • 递推公式为:

      其中,dp[i] 表示一个包含 i 个节点的好二叉树的数量。

  3. 边界条件

    • dp[0] = 1:空树是一个有效的好二叉树。
    • dp[1] = 1:只有一个节点的树也是一个好二叉树。
    • 节点数如果为偶数直接不满足条件返回0

image.png

这里就有一个问题,取模不是应该最后取吗?为什么这里在中间就取了,不会导致结果错误吗?

在动态规划过程中中间取模是否会影响最终结果

理论分析

中间取模是否会影响结果,关键取决于我们如何理解 模运算的性质,特别是在涉及加法和乘法时。我们来详细分析这个问题。

模运算的性质

模运算有几个重要的性质:

  1. 加法的模运算

    • 如果有两个数 a 和 b,那么:

      • 你可以先对每个数取模,然后再进行加法,最后再取模,结果不变。
  2. 乘法的模运算

    • 对于两个数a和b,有:

      • 你可以先对 ab 取模,再进行乘法,然后最后对结果取模,结果不变。

中间取模是否影响结果?

根据上述模运算性质,我们可以得出结论:

中间取模不会影响最终的计算结果。这是因为:

  • 在每次更新 dp[nodes] 时,我们在加法和乘法运算过程中对中间结果进行取模,这样做并不会改变最终的结果,只是确保计算过程中中间结果始终保持在一个合理的范围内。
  • 最终得到的结果与中间是否取模是一样的,只不过中间取模可以防止结果过大,从而避免数值溢出,并且符合题目要求(通常题目要求对 MOD 取模,防止结果过大)。

所以通过这个题,在AI工具的帮助下又掌握了取模的技巧。