题目
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为节点数,队列的长度最多不会超过节点数