对称二叉树:给定一个二叉树,检查它是否是镜像对称的 每周一题(20210131期)
对称二叉树:给定一个二叉树,检查它是否是镜像对称的。
例如,二叉树 [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)递归
如果一个树的左子树与右子树镜像对称,那么这个树是对称的。
因此,该问题可以转化为:两个树在什么情况下互为镜像?
如果同时满足下面的条件,两个树互为镜像:
1、它们的两个根结点具有相同的值
2、每个树的右子树都与另一个树的左子树镜像对称相等
那么重点来了:左子树和右子相等,也就是说要递归的比较左子树和右子树。
我们将根节点的左子树记做 left,右子树记做 right。比较 left 是否等于 right,不等的话直接返回就可以了。
如果相当,比较 left 的左节点和 right 的右节点,再比较 left 的右节点和 right 的左节点
比如看下面这两个子树(他们分别是根节点的左子树和右子树),能观察到这么一个规律:
左子树 2 的左孩子 == 右子树 22的右孩子
左子树 2 的右孩子 == 右子树 2 的左孩子
2 2
/ \ / \
3 4 4 3
/ \ / \ / \ / \
8 7 6 5 5 6 7 8
根据上面信息可以总结出递归函数的两个条件:
终止条件:
1、left 和 right 不等,或者 left 和 right 都为空
2、递归的比较 left,left 和 right.right,递归比较 left,right 和 right.left
(2)迭代
回想下递归的实现:
当两个子树的根节点相等时,就比较:
左子树的 left 和 右子树的 right,这个比较是用递归实现的。
现在我们改用队列来实现,思路如下:
1、首先从队列中拿出两个节点(left 和 right)比较
2、将 left 的 left 节点和 right 的 right 节点放入队列
3、将 left 的 right 节点和 right 的 left 节点放入队列
时间复杂度是 O(n),空间复杂度是 O(n)
注意:一般递归想改为非递归的话用栈,迭代用队列,看是不是率先得到最后一层节点,是的话用栈,否则用队列
三、代码
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public boolean isSymmetric(TreeNode root) {
//方法一:递归
if(root == null) {
return true;
} else {
return leftRight(root.left,root.right);
}
//方法二:迭代
/*
//1、判断根节点的情况
if(root == null || (root.left == null && root.right == null)) {
return true;
}
//2、创建一个队列用于保存节点
Queue<TreeNode> queue = new LinkedList<>();
queue.add(root.left);
queue.add(root.right);
//3、循环判断
while(!queue.isEmpty()) {
//4、从队列中取出两个节点,再比较这两个节点
TreeNode lnode = queue.poll();
TreeNode rnode = queue.poll();
//5、如果两个节点都为空就继续循环,两者有一个为空就返回false
if(lnode == null && rnode == null) {
continue;
}
if(lnode == null || rnode == null || lnode.val != rnode.val) {
return false;
}
//6、将左节点的左孩子, 右节点的右孩子放入队列
queue.add(lnode.left);
queue.add(rnode.right);
//7、将左节点的右孩子,右节点的左孩子放入队列
queue.add(lnode.right);
queue.add(rnode.left);
}
return true;
*/
}
//方法一
public boolean leftRight(TreeNode lnode,TreeNode rnode) {
if(lnode == null && rnode == null) {
return true;
}
if(lnode == null || rnode == null || lnode.val != rnode.val) {
return false;
} else {
return leftRight(lnode.left,rnode.right) && leftRight(lnode.right,rnode.left);
}
}
}
小编新建了一个资料共享群,里面有各种开发学习资料以及实战项目,价值几万的培训视频应有尽有,欢迎大家学习加入。