题目描述
给定一个二叉树,检查它是否是镜像对称的。
例如,二叉树 [1,2,2,3,4,4,3]
是对称的。
但是下面这个 [1,2,2,null,3,null,3]
则不是镜像对称的:
假设二叉树的节点定义如下所示:
public class TreeNode {
public int val;
public TreeNode left;
public TreeNode right;
public TreeNode() {
}
public TreeNode(int val) {
this.val = val;
}
public TreeNode(int val, TreeNode left, TreeNode right) {
this.val = val;
this.left = left;
this.right = right;
}
}
题解
其实所谓的镜像对称,就是沿中间画一条竖线,折叠起来值相等,能重合,如下图,相同颜色的节点值相等,是一颗镜像对称的二叉树。
如下就不是一个镜像对称的二叉树
递归解法:
如下图所示,用两种颜色标识左半部分和右半部分,我们可以实现这样一个递归函数,通过「同步移动」两个指针的方法来遍历这棵树,p 指针和 q 指针一开始都指向这棵树的根,随后 p 右移时,q 左移,p 左移时,q 右移。每次检查当前 p 和 q 节点的值是否相等,如果相等再判断左右子树是否对称。
经过上面分析代码如下
private static boolean isSymmetric(TreeNode root) {
return check(root, root);
}
private static boolean check(TreeNode p, TreeNode q) {
//说明是对称的
if (p == null && q == null) {
return true;
}
//只要有一个为空,说明不是对称的
if (p == null || q == null) {
return false;
}
//如果两个都不为空,则对应的值必须相等,并且 p 左移[即p.left] 和 q 右移[即q.right] 必须也同步是对称节点,并且 p 右移 和 q 左移也同步是对称节点
return p.val == q.val && check(p.left, q.right) && check(p.right, q.left);
}
迭代解法:定义一个辅助队列,定义两个指针 p 和 q分别指向 root ,起始时把 p 和 q入队列
出栈两个节点
(1)如果两个节点相等,则同时执行 p 左移 「即p.left」 和 q 右移「即q.right」 入队列, p 右移「即p.right」 和 q 左移「即q.left」入队列
(2)如果两个节点不相等,则可以直接返回false。
经过上面的分析代码如下:
private static boolean isSymmetric(TreeNode root) {
return check(root, root);
}
private static boolean check(TreeNode p, TreeNode q) {
//定义一个队列
Queue<TreeNode> queue = new LinkedList<>();
//起始时把两个节点入队列
queue.offer(p);
queue.offer(q);
while (!queue.isEmpty()) {
//出队列两个节点
p = queue.poll();
q = queue.poll();
//如果两个节点为空,则继续执行后续操作
if (p == null && q == null) {
continue;
}
//如果节点不相等,则判定不是对称的,可以直接返回false
if ((p == null || q == null) || p.val != q.val) {
return false;
}
//则p左移 和 q右移 入队列
queue.offer(p.left);
queue.offer(q.right);
//p 右移 和 q 左移 入队列
queue.offer(p.right);
queue.offer(q.left);
}
return true;
}