这是我参与11月更文挑战的第3天,活动详情查看:2021最后一次更文挑战
对称二叉树
给定一个二叉树,检查它是否是镜像对称的。
例如,二叉树 [1,2,2,3,4,4,3] 是对称的。
1
/ \
2 2
/ \ / \
3 4 4 3
但是下面这个 [1,2,2,null,3,null,3] 则不是镜像对称的:
1
/ \
2 2
\ \
3 3
进阶:
你可以运用递归和迭代两种方法解决这个问题吗?
解题
解题思路
老规矩我们先整理下我们对此题的一些想法。
本题是常见的二叉树的题目,所以拿到这道题我们先观察上面的对称二叉树,判断二叉树是否是镜像的,我们需要比较子树的对称位置是否相同。即左子树的左侧与右子树右侧,左子树右侧与右子树左侧。
有两种思路,递归方法和迭代方法。
类似的题目有100. 相同的树 和 572. 另一棵树的子树。给出题解100.相同的树 我的题解可以进行参考。
解题过程
方法一: 递归
递归方法给出了两种代码,可以相互参考; 1)判断该二叉树是否为对称的,需要判断每一个节点的左右子节点是否满足条件 对于左右节点来说,判断时要分情况讨论,分别是 root1 == null && root2 == null 、 root1 == null && root2 != null 、 root1 != null && root2 == null 、 root1 != null && root2 != null 这四种情况,第一种情况下是满足对称条件的,第二种和第三种是不满足对称条件的,对于第四种情况,我们需要判断这两个节点的值是否相等来确定是否为对称。 2)**然后需要判断的是 root1.left 和 root2.right 是否满足条件,以及 root1.right 和 root2.left 是否满足条件,**依次进行递归调用即可。
方法二: 迭代
迭代的方法思路也很简单,就是利用队列,分别将需要判断的两个节点压入队列,然后弹出判断上述所说的四种情况即可。 迭代使用的方法有双端队列和普通队列两种。
代码实现
递归
判断一个二叉树是否对称,只需判断二叉树的两个子树是否镜像即可。
const isSymmetric = root => {
if (!root) return true;
// 判断两个二叉树是否镜像
const check = (node1, node2) => {
// 两个空树,true
if (!node1 && !node2) return true;
// 只有一个空树,false
if (!node1 || !node2) return false;
// 镜像的条件:
// 1. 节点值相等
// 2. node1的左子树和node2的右子树是镜像
// 3. node1的右子树和node2的左子树是镜像
return (
node1.val === node2.val &&
check(node1.left, node2.right) &&
check(node1.right, node2.left)
);
};
// 判断树的两个子树是否镜像即可
return check(root.left, root.right);
};
迭代
利用层序遍历的思想,一层一层判断,是否对称。
const isSymmetric = root => {
if (!root) return true;
// 根节点的左右节点入队
const queue = [root.left, root.right];
while (queue.length) {
// 当前队列的长度
const len = queue.length;
// 每次对比两个节点,所以i=i+2
for (let i = 0; i < len; i += 2) {
// 两个节点出队
const left = queue.shift();
const right = queue.shift();
// 有一个为空,另一个不为空,直接返回false
if ((left && !right) || (!left && right)) return false;
// 两节点都不为空
if (left && right) {
// 值不相等,返回false
if (left.val !== right.val) return false;
// 将两个节点的左右节点,按照对应关系入队
queue.push(left.left, right.right, left.right, right.left);
}
}
}
// 遍历结束返回true
return true;
};
关于对称二叉树的思考和方法今天就分享到这里,同学想看到关于算法面试中的哪些疑难解析,可以给我留言,我们一起再来探讨,我们下篇文章再见。