【LeetCode热题100道笔记】对称二叉树
题目描述
给你一个二叉树的根节点 root , 检查它是否轴对称。
示例 1:
输入:root = [1,2,2,3,4,4,3]
输出:true
示例 2:
输入:root = [1,2,2,null,3,null,3]
输出:false
提示:
树中节点数目在范围 [1, 1000] 内
-100 <= Node.val <= 100
进阶:你可以运用递归和迭代两种方法解决这个问题吗?
思考一:递归
核心是定义「镜像检查函数」,递归验证左右子树的对应节点是否满足镜像条件,本质是深度优先遍历(DFS)。
算法过程
- 边界处理:若树为空(题目提示节点数≥1,可省略),直接返回
true
;否则调用check
函数,传入根节点的左、右子树(从根的左右子树开始验证镜像)。 - 镜像检查函数(check(p, q)):
- 终止条件1:若
p
和q
均为null
(对应位置均无节点),返回true
(符合镜像); - 终止条件2:若
p
和q
中一个为null
、一个非null
(对应位置节点缺失),返回false
(不符合镜像); - 值判断:若
p.val !== q.val
(对应位置节点值不同),返回false
; - 递归验证:递归检查
p
的左子树与q
的右子树(镜像位置1)、p
的右子树与q
的左子树(镜像位置2),两者均为true
才返回true
。
- 终止条件1:若
- 时间复杂度 O(n)O(n)O(n)、空间复杂度 O(h)O(h)O(h)(h为树高)。
代码
/*** Definition for a binary tree node.* function TreeNode(val, left, right) {* this.val = (val===undefined ? 0 : val)* this.left = (left===undefined ? null : left)* this.right = (right===undefined ? null : right)* }*/
/*** @param {TreeNode} root* @return {boolean}*/
var isSymmetric = function(root) {return check(root.left, root.right);
};function check(p, q) {if (!p && !q) return true;if ((!p && q) || (p && !q)) return false;if (p.val !== q.val) return false;return check(p.left, q.right) && check(p.right, q.left);
}
思考二:迭代实现(BFS)
核心是用队列存储每一层的节点,通过“相向双指针”验证当前层是否对称,再按“镜像顺序”(右子节点先入队、左子节点后入队)存储下一层节点,本质是广度优先遍历(BFS)。
算法过程
- 初始化队列:若树为空(题目节点数≥1,可省略)返回
true
;否则将根节点的左、右子树入队(从根的左右子树开始验证)。 - 层序遍历与对称验证:
- 当前层验证:定义双指针
l=0
(层首)、r=队列长度-1
(层尾),相向移动检查对应节点:- 若两者一个为
null
、一个非null
,返回false
; - 若均非
null
但值不同,返回false
;
- 若两者一个为
- 存储下一层节点:弹出当前层所有节点,若节点非
null
,按“右子节点→左子节点”的顺序入队(保证下一层验证时,对应位置仍是镜像节点);
- 当前层验证:定义双指针
- 循环终止:若所有层均验证通过,队列空时返回
true
。
- 时间复杂度 O(n)O(n)O(n)、空间复杂度 O(n)O(n)O(n)(队列存储)。
代码
/*** Definition for a binary tree node.* function TreeNode(val, left, right) {* this.val = (val===undefined ? 0 : val)* this.left = (left===undefined ? null : left)* this.right = (right===undefined ? null : right)* }*/
/*** @param {TreeNode} root* @return {boolean}*/
var isSymmetric = function(root) {let queue = [root.left, root.right];while (queue.length) {let tmp = [];let l = 0, r = queue.length-1;while (l < r) {if (!queue[l] || !queue[r]) {if (queue[l] || queue[r]) {return false;}} else if (queue[l].val !== queue[r].val) {return false;}l++;r--;}while (queue.length) {let p = queue.pop();if (p) {tmp.push(p.right);tmp.push(p.left);}}queue = tmp;}return true;
};