面试题28. 对称的二叉树(101. 对称二叉树)(Java)(遍历递归;翻转二叉树 + 判断二叉树是否一样)(遍历递归)(队列)

28 篇文章 0 订阅
7 篇文章 0 订阅

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;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值