「剑指 Offer 28.对称的二叉树」
Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情。
题目描述(level 简单)
请实现一个函数,用来判断一棵二叉树是不是对称的。如果一棵二叉树和它的镜像一样,那么它是对称的。
示例
例如,二叉树 [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:
输入:root = [1,2,2,3,4,4,3]
输出:true
示例 2:
输入:root = [1,2,2,null,3,null,3]
输出:false
思路分析
应该是对剑指 Offer 27的承接,上一题需要求导的是二叉树的镜像,第一想法是想通过BFS广度优先搜索
也就是层序遍历
来实现镜像的对比,但是实际操作过程中,发现代码量有点偏多,很容易绕进去。并且也不是很好看。既然是树之类的问题,无非就是两种思路:递归
跟遍历
。既然遍历不行那就试试递归的方法能不能解决。还是要在提一下,递归的两个过程递推
与回溯
。当然还是要放弃在脑中“展开递归”这种做法,毕竟套娃很容易就会被套进去了。
- 递归出口分析
1
/ \
2 2
/ \ / \
3 4 4 3
根据题目意思,一个二叉树是不是对称的(成镜像对称),这个小学就学过,存在中线,沿中线对折后完全重合即为镜像对称,代到示例中也即是满足几个条件(从上到下):
- 左右的高度是一样的,不然够不成对称
- 对于对称的两个节点
A、B
一定有A.val = B.val
(设左侧2为A节点,右侧2为B节点) - 最左侧的
3
与最右侧的3
是对成的,也即是A.left.val = B.right.val
,同理可得A.right.val = B.left.val
转化成递归
的出口条件
- 对成节点同时为空时即
A == null && B == null
则返回true
,(对称的一种特殊形式),条件一 - 往下
递推
,到这里则表明条件一
不成立,那么A、B
不同时为空,则会有:A为空,B不为空
,A不为空,B为空
,A、B都不为空
。A、B都不为空时比较其对应的值val
如果A.val != B.val
则不对称。条件二(判断不是镜像的条件) - 最后比较
A.left
与B.right
的对称性,如果一致说明最外层是对称的了,当然这还不够,还需要比较“内部”的对称性A.right
与B.left
的对称性,如果也对称,那么整颗树就是对称的。
代码实现
//树节点
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) {
val = x;
}
}
public class Solution {
public boolean isSymmetric(TreeNode root) {
return null == root ? true : compare(root.left, root.right);
}
private boolean compare(TreeNode a, TreeNode b) {
//条件一
if(null == a && null == b) {
return true;
}
//条件二
if(null == a || null == b || a.val != b.val) {
return false;
}
return compare(a.left, b.right) && compare(a.right, b.left);
}
}
复杂度
时间复杂度O(N):每次比较的是一对节点,设节点总数为N,所以比对的次数为N/2,时间复杂度为O(N)
空间复杂度O(N):考虑树退化成链表(一般都会考虑到这层情况)