[前端]_一起刷leetcode 101. 对称二叉树

106 阅读3分钟

大家好,我是挨打的阿木木,爱好算法的前端摸鱼老。最近会频繁给大家分享我刷算法题过程中的思路和心得。如果你也是想提高逼格的摸鱼老,欢迎关注我,一起学习。

题目

101. 对称二叉树

给定一个二叉树,检查它是否是镜像对称的。

 

例如,二叉树 [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

 

进阶:

你可以运用递归和迭代两种方法解决这个问题吗?

递归解法

思路

  1. 判断当前根节点是否存在,存在的话判断左节点和右节点的值是否相等;
  2. 判断左节点和右节点是否相等之前,先做一个边界值的限制。如果左子节点和右子节点都不存在,说明它们是相等的,如果它们只有一个存在,说明是不相等的;
  3. 边界判断完之后,判断一下当前两个值是否相等,如果相等了,递归的判断当前左节点的左子节点和右节点的右子节点是否相等,左节点的右子节点和右节点的左子节点是否相等即可;
  4. 因为是镜像的,我们每轮只需要判断我们要比较的两个节点是否镜像全等即可。

实现

/**
 * 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 !root || compareNode(root.left, root.right);
};

function compareNode(node1, node2) {
    if (!node1 && !node2) return true;
    if (!node1 || !node2) return false;

    return node1.val === node2.val && compareNode(node1.left, node2.right) && compareNode(node1.right, node2.left)
}

迭代解法

思路

  1. 除了第一轮,后面每轮的节点数都是双数的,我们只需要维持好他们彼此的关系即可;
  2. 判断的时候需要先判断节点是否为空节点,如果只有一个节点是空节点说明不匹配;
  3. 如果两个节点都是空节点的跳过,不进行任何操作;
  4. 如果两个节点都不是空节点,那么要比较他们的值,而且还有比较第一个节点的左节点和第二个节点的右节点,第一个节点的右节点和第二个节点的左节点的值,我们依次把他们放进下一轮的数组中即可;
  5. 每一轮一号节点的子节点用unshift插入数组的最前面,二号节点的子节点用push插入数组的最后面,然后我们取值的时候也是从两边各自取一个,不过需要注意一点,插入的顺序得是1号的右 => 对应2号的左,1号的左对应2号的右,意思就是1号先插入右2号就得先插入左。
/**
 * 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) {
    if (!root) return true;
    let arr = [ root.left, root.right ];

    
    while (arr.length) {
        let nextArr = [];
        const mid = arr.length / 2;
        for (let i = 0; i < mid; i++) {
            let first = arr[i], last = arr[arr.length - 1 - i];
            // 有一个空节点,排除
            if (!!first !== !!last) return false;
            // 两个都是空结点,抬走下一位
            if (!first) continue;

            // 如果值不相等就不用比了
            if (first.val !== last.val) {
                return false;
            } else {
                // 前面的放前面,后面的放后面, 形成镜像
                nextArr.unshift(first.right);
                nextArr.unshift(first.left);
                nextArr.push(last.left);
                nextArr.push(last.right);
            }
        }
        arr = nextArr;
    }

    return true;
};

看懂了的小伙伴可以点个关注、咱们下道题目见。如无意外以后文章都会以这种形式,有好的建议欢迎评论区留言。