小M的好二叉树 | 豆包MarsCode AI 刷题

41 阅读2分钟

解题思路细化

  1. 理解好二叉树的定义

    • 好二叉树中的每个节点要么没有孩子,要么有两个孩子。
    • 这意味着每个非叶子节点都有两个子节点,且树的节点总数 n 必须是奇数(因为每个非叶子节点贡献两个子节点,加上自身一个节点,总数为奇数)。
  2. 动态规划方法

    • 我们可以使用动态规划来解决这个问题。定义 dp[i] 为有 i 个节点时可以构成的好二叉树的数量。

    • 初始条件:dp[1] = 1(只有一个节点时,只有一种树结构)。

    • 状态转移方程:对于每个节点数 i,我们可以将其分解为根节点和左右子树。假设左子树有 j 个节点,右子树有 i-1-j 个节点(因为根节点占用一个节点),则有:

      plaintext

      dp[i] += dp[j] * dp[i-1-j]

    • 注意:j 和 i-1-j 都必须是奇数,因为左右子树也必须是好二叉树。

  3. 取模运算

    • 由于结果需要对 10^9 + 7 取模,我们在每次计算 dp[i] 时都要进行取模运算。

关键思路提示

  1. 初始化

    • 确保 dp[1] = 1,因为只有一个节点时,只有一种树结构。
  2. 动态规划计算

    • 使用双重循环计算 dp[i],外层循环遍历所有奇数节点数 i,内层循环遍历所有可能的左子树节点数 j
    • 内层循环中,确保 j 和 i-1-j 都是奇数。
  3. 取模运算

    • 每次计算 dp[i] 时都要进行取模运算,以防止溢出。
public class Main {
    public static int solution(int n) {
        // 如果节点数不是奇数,直接返回0
        if (n % 2 == 0) return 0;
        
        // 定义dp数组
        int[] dp = new int[n + 1];
        dp[1] = 1; // 初始条件
        
        // 取模常数
        int MOD = 1000000007;
        
        // 动态规划计算dp数组
        for (int i = 3; i <= n; i += 2) {
            for (int j = 1; j < i; j += 2) {
                dp[i] = (dp[i] + dp[j] * dp[i - 1 - j]) % MOD;
            }
        }
        
        return dp[n];
    }

    public static void main(String[] args) {
        System.out.println(solution(5) == 2);
        System.out.println(solution(7) == 5);
        System.out.println(solution(9) == 14);
    }
}

关键步骤

  1. 初始化dp[1] = 1
  2. 动态规划计算:使用双重循环计算 dp[i],注意 i 和 j 都是奇数。
  3. 取模运算:每次计算 dp[i] 时都要进行取模运算。

通过上述思路和伪代码框架,你可以逐步实现代码并验证其正确性