1 条题解

  • 0
    @ 2025-11-11 13:19:44

    题目理解

    我们需要在一棵给定的二叉树中,找到一个节点数最多的对称二叉子树。

    对称二叉树的定义

    1. 必须是二叉树
    2. 将树中所有节点的左右子树交换后,新树与原树在结构上完全相同,且对应节点的权值相等

    注意:单节点树(只有树根)也是对称二叉树。

    关键概念分析

    1. 对称性的理解

    对于一棵以节点 rr 为根的二叉树,它是对称二叉树当且仅当:

    • 根节点 rr 的权值任意
    • rr 的左子树与右子树是镜像对称

    更具体地说,如果设:

    • 左子树为 LL,右子树为 RR
    • 那么 LLRR 必须满足:
      • LL 的根节点权值 = RR 的根节点权值
      • LL 的左子树 与 RR 的右子树 对称
      • LL 的右子树 与 RR 的左子树 对称

    2. 递归定义

    用递归的方式定义对称性检查函数 is_symmetric(u, v)

    • 如果 uuvv 都为空,返回真
    • 如果 uuvv 一个为空一个不为空,返回假
    • 如果 uuvv 的权值不相等,返回假
    • 否则递归检查:
      • is_symmetric(u.left, v.right)
      • is_symmetric(u.right, v.left)

    那么以 rr 为根的树是对称二叉树当且仅当:

    • is_symmetric(r.left, r.right)

    算法设计

    1. 暴力解法(小数据)

    最直接的方法是:

    1. 枚举每个节点作为候选子树的根
    2. 检查以该节点为根的子树是否对称
    3. 如果对称,记录节点数并更新最大值

    复杂度分析

    • 枚举 nn 个节点
    • 每次检查对称性需要 O(k)O(k),其中 kk 是子树大小
    • 最坏情况下 O(n2)O(n^2),对于 n106n \leq 10^6 不可行

    2. 优化思路

    关键观察:如果一棵树是对称二叉树,那么它的左右子树必须结构相同。

    我们可以利用这个性质进行剪枝:

    • 在检查对称性时,如果发现子树大小不同,直接返回不对称
    • 预处理每个节点的子树大小

    3. 高效算法框架

    1. 预处理

      • 计算每个节点的子树大小 size[u]
      • 计算每个节点的子树哈希值(可选,用于快速比较)
    2. 对称性检查优化

      • 先比较左右子树的 size,如果不同则直接返回假
      • 然后递归检查对称性
    3. 遍历策略

      • 使用 DFS 遍历每个节点
      • 对于每个节点,检查以其为根的子树是否对称
      • 如果对称,用 size[u] 更新答案

    4. 哈希优化

    对于大数据(n106n \leq 10^6),我们可以使用树哈希来加速对称性检查:

    • 为每个子树计算一个哈希值
    • 比较左右子树的哈希值来判断是否对称
    • 但需要注意哈希冲突的可能性

    哈希函数设计示例:

    hash[u] = (val[u] * base^3 + hash[left] * base^2 + hash[right] * base + size[u]) % mod
    

    对称检查时,比较:

    hash[left] 与 镜像哈希(right)
    

    其中镜像哈希是交换左右子树计算得到的哈希值。

    特殊情况处理

    1. 满二叉树和完全二叉树

    对于测试点 9-16,树是满二叉树或完全二叉树,这大大简化了问题:

    • 结构已知,对称性检查更简单
    • 可以利用层次遍历的性质

    2. 权值全为 1

    对于测试点 17-20,所有节点权值都是 1:

    • 只需要检查结构对称,不需要比较权值
    • 进一步简化了问题

    3. 边界情况

    • 空节点的处理
    • 单节点树(总是对称)
    • 只有左子树或只有右子树的节点

    算法步骤总结

    1. 读入数据:存储树的邻接表结构和节点权值
    2. 预处理子树大小:通过 DFS 计算每个节点的 size[u]
    3. (可选)预处理哈希值:为大数据准备
    4. 检查对称性:对于每个节点,检查以其为根的子树是否对称
    5. 更新答案:如果对称,用 size[u] 更新最大节点数

    复杂度分析

    • 预处理子树大小O(n)O(n)
    • 对称性检查:最坏情况下 O(n2)O(n^2),但通过剪枝可以优化
    • 实际表现:由于对称二叉树的限制很强,大部分子树很快就会被剪枝

    实现技巧

    1. 记忆化:对于已经检查过的子树对,可以缓存结果
    2. 提前终止:在 DFS 过程中,如果当前子树大小已经小于当前最大答案,可以提前返回
    3. 层次剪枝:从底层往顶层检查,利用子树的对称性信息

    总结

    这道题的核心在于理解对称二叉树的递归定义,并通过合理的剪枝策略来优化算法:

    1. 问题本质:在二叉树中寻找最大的镜像对称子树
    2. 关键观察:对称性具有递归结构,左右子树必须互为镜像
    3. 优化策略:子树大小剪枝、哈希加速、记忆化
    4. 特殊情况:满二叉树、完全二叉树、权值均匀等情况可以特殊处理

    通过深入分析对称性的性质,我们可以在较大的数据范围内高效地解决这个问题。这种"递归检查 + 剪枝优化"的思路在树形结构问题中非常常见且有效。

    • 1

    #3008. 「NOIP2018 普及组」对称二叉树

    信息

    ID
    5235
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    8
    已通过
    1
    上传者