[路飞]_leetcode刷题_101. 对称二叉树

110 阅读2分钟

题目

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

思路:

递归,二叉树的前序遍历。

  • 比较根节点的左子树和右子树

  • 用左子树左节点和右子树的右节点比较。

  • 用左子树右节点和右子树的左节点比较。

代码如下:

/**
 * @param {TreeNode} root
 * @return {boolean}
 */
var isSymmetric = function(root) {
    if(!root) return true;
    return isSameNode(root.left,root.right)
};

function isSameNode(left,right){
    if(left == null || right == null) return left == right;

    return left.val == right.val && isSameNode(left.left,right.right) && isSameNode(left.right,right.left)

}

复杂度分析:

时间复杂度:O(n),n为节点数,因为需要遍历所有的节点,

空间复杂度:O(n),n为二叉树的高度,该题当二叉树为链表的时候,返回false。最坏的情况是左子树只有left,右子树只有right,这种情况高度为n-1/2,去掉常数也是O(n)

思路2:

迭代,广度优先遍历

  • 首先套用最经典的队列法广度优先搜索遍历模版。

  • 这里要改变一点,我们开始直接push两个root进去,用来做对比。

  • 每次从队列里取,也是连续取两个。

  • 往队列里放,要讲究顺序,先放leftNode.left,再放rightNode.right;然后放rightNode.left,再放leftNode.right。这样可以保证每次连续取出的两个节点刚好是对称节点。

/**
 * @param {TreeNode} root
 * @return {boolean}
 */
var isSymmetric = function(root) {
    let queue = [];
    queue.push(root);
    queue.push(root);
    let leftNode,rightNode;
    while(queue.length>0){
        let size = queue.length;
        while(size>0){
            leftNode = queue.shift();
            rightNode = queue.shift();
            size -= 2;
            if (!leftNode && !rightNode) continue;
            if ((!leftNode || !rightNode) || (leftNode.val !== rightNode.val)) return false;

            queue.push(leftNode.left); 
            queue.push(rightNode.right);

            queue.push(leftNode.right); 
            queue.push(rightNode.left);
        }
    }
    return true;
};

复杂度分析:

时间复杂度:O(n),n为节点数,因为需要把每个节点遍历到

空间复杂度:O(n),n为节点数,队列的长度最多不会超过节点数