对称二叉树
判断一棵二叉树是否是镜像对称的
问题
给定一棵二叉树的根节点 root,判断这棵树是否是镜像对称的。
1
/ \
2 2
/ \ / \
3 4 4 3
上面这棵树是对称的,返回 true。
1
/ \
2 2
\ \
3 3
上面这棵树不对称,返回 false。
解答
递归解法
// 二叉树节点定义
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}
*/
function isSymmetric(root) {
if (root === null) return true;
return isMirror(root.left, root.right);
}
/**
* 判断两棵树是否互为镜像
* @param {TreeNode} left
* @param {TreeNode} right
* @return {boolean}
*/
function isMirror(left, right) {
// 都为空,对称
if (left === null && right === null) return true;
// 只有一个为空,不对称
if (left === null || right === null) return false;
// 值不相等,不对称
if (left.val !== right.val) return false;
// 递归比较:左的左 vs 右的右,左的右 vs 右的左
return isMirror(left.left, right.right) && isMirror(left.right, right.left);
}
迭代解法
/**
* 使用队列迭代判断
* @param {TreeNode} root
* @return {boolean}
*/
function isSymmetricIterative(root) {
if (root === null) return true;
const queue = [root.left, root.right];
while (queue.length > 0) {
// 每次取出两个节点比较
const left = queue.shift();
const right = queue.shift();
// 都为空,继续下一对
if (left === null && right === null) continue;
// 只有一个为空,或值不等
if (left === null || right === null) return false;
if (left.val !== right.val) return false;
// 按镜像顺序入队
queue.push(left.left, right.right);
queue.push(left.right, right.left);
}
return true;
}
测试
// 构建对称树: [1,2,2,3,4,4,3]
const symmetricTree = new TreeNode(
1,
new TreeNode(2, new TreeNode(3), new TreeNode(4)),
new TreeNode(2, new TreeNode(4), new TreeNode(3))
);
// 构建非对称树: [1,2,2,null,3,null,3]
const asymmetricTree = new TreeNode(
1,
new TreeNode(2, null, new TreeNode(3)),
new TreeNode(2, null, new TreeNode(3))
);
console.log(isSymmetric(symmetricTree)); // true
console.log(isSymmetric(asymmetricTree)); // false
关键点
- 对称的本质是左右子树互为镜像
- 镜像比较:左子树的左 对应 右子树的右,左子树的右 对应 右子树的左
- 递归终止条件:两个都为空返回 true,只有一个为空返回 false
- 迭代解法用队列成对存取节点,按镜像顺序入队
- 时间复杂度 O(n),空间复杂度 O(n)
目录