题目描述
给定一个二叉树,检查它是否是镜像对称的。
例如,二叉树 [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
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/symmetric-tree
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解题思路
递归实现
- 镜像对称,就是左右两边相等,也就是左子树和右子树是相当的。
- 左子树和右子相等,意味着递归的比较左子树和右子树。
- 特殊情况处理:
- 如果根节点为null,则对称;
- dfs(root.left,root.right):递归比较根节点的左节点和右节点
- 递归终止条件;
- 两个节点都为null,则对称;
- 两个节点有一个为null,则不对称;
- 两个节点值不相等left.val!==right.val,则不对称;
- 两个节点相等,则进行两个子树的节点是否相等;递归比较;
- return dfs(left.left,right.right)&&dfs(left.right,right.left);
- 递归终止条件;
代码
/**
* Definition for a binary tree node.
* class TreeNode {
* val: number
* left: TreeNode | null
* right: TreeNode | null
* constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) {
* this.val = (val===undefined ? 0 : val)
* this.left = (left===undefined ? null : left)
* this.right = (right===undefined ? null : right)
* }
* }
*/
function isSymmetric(root: TreeNode | null): boolean {
// 1、如果根节点为null,则返回true,对称;
if(root==null){
return true;
}
// 2、否则 比较根节点的左节点,和右节点;
return dfs(root.left,root.right);
};
function dfs(left:TreeNode|null,right:TreeNode|null):boolean{
// 递归的终止条件:
// 3、两个节点都为null,则对称;
if(left==null&&right==null){
return true;
}
// 4、两个节点有一个为null;则非对称;
if(left==null||right==null){
return false;
}
// 5、两个节点值val不相等;则非对称
if(left.val!==right.val){
return false;
}
//否则两节点值相等,进行递归比较
return dfs(left.left,right.right)&&dfs(left.right,right.left);
}
队列实现
回想下递归的实现:思路如下:
- 优先处理特殊情况:
- 当根节点为null,则对称;
- 当左节点为null && 右节点为null;则对称;
- 首先从队列queue中拿出两个节点(left 和 right)入队列;
- 遍历queue;
- 比较队列的两个节点:leftNode,rightNode;
- 左右两个节点相等,则继续进行当前层级的遍历
- 两个节点有一个为null;则非对称;
- 左右节点值不同时;则非对称;
- 队列压入新的比较节点;左节点的左孩子 和 右节点的右孩子
- 队列压入新的比较节点;左节点的右孩子 和 右节点的左孩子
- 比较队列的两个节点:leftNode,rightNode;
时间复杂度是 O(n),空间复杂度是 O(n)。
function isSymmetric(root: TreeNode | null): boolean {
// 优先考虑特殊情况;
// 1、当根节点为null,则对称;
// 2、当左节点为null && 右节点为null;则对称;
if(root==null||(root.left==null&&root.right==null)){
return true;
}
// 否则,使用队列来存储当前比较层级节点;
let queue=[];
queue.push(root.left);
queue.push(root.right);
// 当队列数据存在时,继续执行比较;
while(queue.length>0){
let leftNode=queue.shift();
let rightNode=queue.shift();
//3、左右两个节点相等,则继续进行当前层级的遍历;
if(leftNode==null&&rightNode==null){
continue;
}
// 4、两个节点有一个为null;则非对称;
if(leftNode==null||rightNode==null){
return false;
}
// 5、左右节点值不同时;则非对称;
if(leftNode.val!==rightNode.val){
return false;
}
// 6、否则leftNode.val===rightNode.val;当前比较节点所有可能性比较完毕;
// 队列压入新的比较节点;左节点的左孩子 和 右节点的右孩子
queue.push(leftNode.left);
queue.push(rightNode.right);
// 队列压入新的比较节点;左节点的右孩子 和 右节点的左孩子
queue.push(leftNode.right);
queue.push(rightNode.left);
}
return true;
};