1. 简介
在计算机科学中,二叉树 是一种每个节点最多有两个子节点的数据结构。
本文将介绍如何判断一个二叉树是否对称。
2. 什么是对称二叉树?
在二叉树中,每个节点包含两个子树:左子树和右子树。一个子树可以是空、一个单独的节点,或者另一个完整的二叉树。
如果根节点的左子树是右子树的镜像反射,那么这棵二叉树就是对称的。
例如,下面这棵树是对称的:
而下面这棵树虽然左右子树结构相同,但值不同,因此不是对称的:
3. 递归解法
根据对称的定义,我们可以使用如下规则来判断两个二叉树是否互为镜像:
- 两个根节点的值必须相同
- 一棵树的左子树必须与另一棵树的右子树互为镜像
将这些条件转换为递归实现如下:
boolean isSymmetric(TreeNode root) {
if (root == null) {
return true;
}
return isMirror(root.left, root.right);
}
boolean isMirror(TreeNode root1, TreeNode root2) {
if (root1 == null && root2 == null) return true;
if (root1 == null || root2 == null) return false;
return root1.val == root2.val
&& isMirror(root1.left, root2.right)
&& isMirror(root1.right, root2.left);
}
这段代码中,我们使用了一个辅助函数 isMirror
来判断两个子树是否镜像对称。先处理空节点的情况,再递归比较左右子树。
时间复杂度: O(n)
,其中 n
是节点总数。我们每个节点访问一次。
4. 迭代解法
除了递归,我们也可以使用迭代方式实现。思路是:按层遍历,每一层的节点应呈现对称结构。
比如下图中的结构,每层节点应满足对称特性:
实现方式是使用一个队列来辅助遍历:
boolean isSymmetric(TreeNode root) {
if (root == null) return true;
Queue<TreeNode> queue = new LinkedList<>();
queue.add(root.left);
queue.add(root.right);
while (!queue.isEmpty()) {
TreeNode node1 = queue.poll();
TreeNode node2 = queue.poll();
if (node1 == null && node2 == null) continue;
if (node1 == null || node2 == null) return false;
if (node1.val != node2.val) return false;
queue.add(node1.left);
queue.add(node2.right);
queue.add(node1.right);
queue.add(node2.left);
}
return true;
}
每次从队列中取出两个节点进行比较,然后将它们的子节点以镜像顺序入队。这种方式也保证了我们访问了所有节点一次。
✅ 优点: 避免递归可能导致的栈溢出问题
❌ 缺点: 实现略复杂,需要维护队列结构
时间复杂度: O(n)
,每个节点访问一次
5. 小结
本文介绍了判断二叉树是否对称的两种方法:
- ✅ 递归法:实现简单,逻辑清晰,适合大多数场景
- ✅ 迭代法:避免栈溢出问题,适合处理深度较大的树
两种方法的时间复杂度均为 O(n)
,空间复杂度取决于树的高度或队列的长度。
踩坑提醒:
- 在判断镜像时容易搞混左右子树的顺序,建议画图辅助理解
- 注意空节点的处理,否则容易出现空指针异常
选择实现方式时,建议优先使用递归,逻辑清晰,除非遇到递归深度限制问题再考虑迭代实现。