1 题目
请实现一个函数,用来判断一棵二叉树是不是对称的。如果一棵二叉树和它的镜像一样,那么它是对称的。
示例 1:
输入:root = [1,2,2,3,4,4,3]
输出:true
示例 2:
输入:root = [1,2,2,null,3,null,3]
输出:false
限制:
0 <= 节点个数 <= 1000
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/dui-cheng-de-er-cha-shu-lcof
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
2 Java
2.1 方法一(遍历遍历递归;翻转二叉树 + 判断二叉树是否一样)
先翻转二叉树,再比较翻转前后是否相等
注!:不能直接翻转原树(原树不能被修改),必须翻转产生一个新的树。然后两树进行比较
/**
* 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) {
TreeNode root2 = mirrorTree(root);
return isEqual(root, root2);
}
// 判断两个二叉树是否一模一样
public boolean isEqual(TreeNode root1, TreeNode root2){
// if出口
if(root1 == null && root2 == null) return true;
if(root1 == null || root2 == null) return false;
// for多路选择
boolean m = root1.val == root2.val;
boolean l = isEqual(root1.left, root2.left);
boolean r = isEqual(root1.right, root2.right);
return m && l && r;
}
// 226. 翻转二叉树;不过这个解法并没有翻转原树,而是产生了一个翻转后的新树
public TreeNode mirrorTree(TreeNode root) {
if(root == null) return null;
// 后序遍历
TreeNode rL = mirrorTree(root.left);
TreeNode rR = mirrorTree(root.right);
TreeNode newRoot = new TreeNode(root.val);
newRoot.left = rR;
newRoot.right = rL;
return newRoot;
}
}
!2.2 方法二(前序递归,不好理解)
一棵树是否镜像
等价于
左、右子树这两棵树是否镜像对称
即
两棵树是否镜像(!!!这才是需要递归的子问题!!!)
两棵树镜像的条件
1 根节点值相同
2 root1左子树 与 root2右子树,root1右子树 与 root2左子树,两两互为镜像
/**
* 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) {
// 镜像对称的树:根节点非null,左、右两颗子树镜像对称
if(root == null) return true;
return isSymmetric(root.left, root.right);
}
// 判断两棵树是否镜像对称
public boolean isSymmetric(TreeNode root1, TreeNode root2){
// if出口
if(root1 == null && root2 == null) return true;
if(root1 == null || root2 == null) return false;
// for多路选择
// 镜像对称的两棵树:根节点相等,树1的左子树 与 树2的右子树 镜像对称,树1的右子树 与 树2的左子树 镜像对称
boolean m = root1.val == root2.val;
boolean l = isSymmetric(root1.left, root2.right);
boolean r = isSymmetric(root1.right, root2.left);
return m && l && r;
}
}
注:
递归方法(下面那个)有两个TreeNode参数,所以特殊情况多:
1 两树皆为null
2 有一个为null
3 都不为null
特殊情况,就是围绕参数是否为null讨论,n个参数n二次方个情况
讨论特殊情况是为了避免 root 为 null 的情况下调用 root.val 或者 root.left
2.3 方法三(队列迭代)
队列中每两个连续的结点应该是相等的,而且它们的子树互为镜像。
每次提取两个结点并比较它们的值。然后,将两个结点的左右子结点按相反的顺序插入队列中。
这个方法由于开始压两个root入队列,导致徒增一倍工作量,不好
/**
* 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;
Queue<TreeNode> q = new LinkedList<TreeNode>();
q.add(root);
q.add(root);
while(!q.isEmpty()){
TreeNode tree1 = q.poll();
TreeNode tree2 = q.poll();
if(tree1 == null && tree2 == null) continue;
if(tree1 == null || tree2 == null) return false;
if(tree1.val != tree2.val) return false;
q.add(tree1.left);
q.add(tree2.right);
q.add(tree1.right);
q.add(tree2.left);
}
return true;
}
}