【面试算法专栏及回答思考】——对称二叉树

353 阅读3分钟

这是我参与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;
};

关于对称二叉树的思考和方法今天就分享到这里,同学想看到关于算法面试中的哪些疑难解析,可以给我留言,我们一起再来探讨,我们下篇文章再见。