【每天学习一点算法 2025/12/18】对称二叉树

每天学习一点算法 2025/12/18

题目:对称二叉树

给你一个二叉树的根节点 root , 检查它是否轴对称。

  1. 老规矩先来递归, 检查二叉树是否轴对称,我们是不是得比较根节点下面得两个子树是否是轴对称,那么我们只需要递归比较两个子树的值即可,那要怎么传参呢?首先肯定是要将根节点的两个子节点作为初始传参传进去的,那么我们需要一个辅助函数,然后每次递归对称传递子结点比较。

    typescript 复制代码
    function isSymmetric(root: TreeNode | null): boolean {
      if (!root) return true; // 空树默认为true
      // 定义辅助函数 递归比较两个子树
      function validate(left: TreeNode | null, right: TreeNode | null): boolean {
        // 两个子节点同时为空才有轴对称的可能
        if (!left && !right) return true;
        if (!left || !right) return false;
        // 比较左右子节点的值,并传递对称的子节点递归
        return left.val === right.val && validate(left.left, right.right) && validate(left.right, right.left);
      }
    	// 调用辅助函数
      return validate(root.left, root.right);
    };
  2. 还有我们是不是可以用层序遍历的方法取得每一层的节点然后我们校验他们是否是对称就行了。核心思想其实跟递归是一样的,找到对称节点作比较。

    如果我们拓展下一层按照左左↔右右、左右↔右左的顺序入队列,那么每两个节点都是对称位置上的节点了,比如说我们有一个四层的结构对称的树,像下面这个样。

    复制代码
                1
            /       \
         2            3
        /   \       /   \
       4     5     6     7
      / \   / \   / \   / \
     8   9 10 11 12 13 14 15
    • 我们初始两个子节点入队列: [2, 3]
    • 然后 2, 3 出队列,子节点按照左左↔右右、左右↔右左的顺序入队列:[4, 7, 5, 6]
    • 然后 4, 7 出队列,子节点按照左左↔右右、左右↔右左的顺序入队列:[5, 6, 8, 15, 9, 14]
    • 然后 5, 6 出队列,子节点按照左左↔右右、左右↔右左的顺序入队列:[8, 15, 9, 14, 10, 13, 11, 12]
    • 然后剩下的子节点两两出队列。

    可以看到整个循环的过程子节点的遍历是从上到下,每层从两端向中间收拢的,我们按照这种方式遍历比较两两出队列的节点值就可判断出树是否对称。

    typescript 复制代码
    function isSymmetric(root: TreeNode | null): boolean {
      // 空树默认为对称
      if (!root) return true;
      // 初始化队列,用于层序遍历对称位置的节点
      const queue: Array<TreeNode | null > = [];
    
      // 根节点的左右子节点都为空,是对称树
      if (!root.left && !root.right) return true;
      // 根节点的左右子节点只有一个为空,必然不对称
      if (!root.left || !root.right) return false;
    
      // 将根节点的左右子节点(对称的起始节点)入队
      queue.push(root.left);
      queue.push(root.right);
    
      // 层序遍历队列中的对称节点对
      while (queue.length) {
        // 每次取出队列前两个节点(一对对称节点)
        const left = queue.shift()!;
        const right = queue.shift()!;
    
        // 两个节点都为空,说明当前对称位置无节点,继续检查下一对
        if (!left && !right) continue;
    
        // 不对称的情况:
        // 1. 其中一个节点为空,另一个非空
        // 2. 两个节点值不相等
        if ((!left || !right) || (left.val !== right.val)) return false;
    
        // 按对称规则将下一层节点入队:
        // 左节点的左子节点对应右节点的右子节点
        queue.push(left.left);
        queue.push(right.right);
        // 左节点的右子节点对应右节点的左子节点
        queue.push(left.right);
        queue.push(right.left);
      }
    
      // 所有对称节点对都验证通过,说明是对称二叉树
      return true;
    }

题目来源:力扣(LeetCode)

相关推荐
草履虫建模16 小时前
力扣算法 1768. 交替合并字符串
java·开发语言·算法·leetcode·职场和发展·idea·基础
naruto_lnq18 小时前
分布式系统安全通信
开发语言·c++·算法
Jasmine_llq18 小时前
《P3157 [CQOI2011] 动态逆序对》
算法·cdq 分治·动态问题静态化+双向偏序统计·树状数组(高效统计元素大小关系·排序算法(预处理偏序和时间戳)·前缀和(合并单个贡献为总逆序对·动态问题静态化
ASKED_201919 小时前
Langchain学习笔记一 -基础模块以及架构概览
笔记·学习·langchain
爱吃rabbit的mq19 小时前
第09章:随机森林:集成学习的威力
算法·随机森林·集成学习
(❁´◡`❁)Jimmy(❁´◡`❁)20 小时前
Exgcd 学习笔记
笔记·学习·算法
YYuCChi20 小时前
代码随想录算法训练营第三十七天 | 52.携带研究材料(卡码网)、518.零钱兑换||、377.组合总和IV、57.爬楼梯(卡码网)
算法·动态规划
不能隔夜的咖喱20 小时前
牛客网刷题(2)
java·开发语言·算法
VT.馒头20 小时前
【力扣】2721. 并行执行异步函数
前端·javascript·算法·leetcode·typescript
进击的小头21 小时前
实战案例:51单片机低功耗场景下的简易滤波实现
c语言·单片机·算法·51单片机