力扣热门100题——对称二叉树

8、对称二叉树

1.问题描述

给你一个二叉树的根节点 root , 检查它是否轴对称。

2.示例

示例 1:

输入:root = [1,2,2,3,4,4,3]
输出:true
示例 2:

输入:root = [1,2,2,null,3,null,3]
输出:false

3.提示

树中节点数目在范围 [1, 1000] 内
-100 <= Node.val <= 100

4.进阶

你可以运用递归和迭代两种方法解决这个问题吗?

5.具体解法

//方法一:递归
//判断一个二叉树是否对称只需要去看他的左子树和右子树是否相等,进而找到了递归的点
//我们可以实现这样一个递归函数,通过「同步移动」两个指针的方法来遍历这棵树,
//p指针和q指针一开始都指向这棵树的根,随后p右移时,q左移,p左移时,q右移。每次检查当前p和q节点的值是否相等,如果相等再判断左右子树是否对称。判断左右子树就是一种递归,注意是p.left和q.right去做比较

/*
class Solution {
    public boolean isSymmetric(TreeNode root) {
        return check(root, root);
    }

    public boolean check(TreeNode p, TreeNode q) {
        if (p == null && q == null) {
            return true;
        }
        if (p == null || q == null) {
            return false;
        }
        return p.val == q.val && check(p.left, q.right) && check(p.right, q.left);
    }
}
 */
 
//方法二:迭代
//那么如何用迭代的方法实现呢?首先我们引入一个队列,这是把递归程序改写成迭代程序的常用方法。
//初始化时我们把根节点入队两次。
//每次提取两个结点并比较它们的值(队列中每两个连续的结点应该是相等的,而且它们的子树互为镜像),
//然后将两个结点的左右子结点按相反的顺序插入队列中。
//当队列为空时,或者我们检测到树不对称(即从队列中取出两个不相等的连续结点)时,该算法结束。

/*
class Solution {
    public boolean isSymmetric(TreeNode root) {
        return check(root, root);
    }

    public boolean check(TreeNode u, TreeNode v) {//这个方法同时操作两个结点
        Queue<TreeNode> q = new LinkedList<TreeNode>();
        q.offer(u);
        q.offer(v);//因为第一次uv都是root,所以根节点是进去两次
                   //offer()方法的作用是:如果在不违反容量限制的情况下立即执行,则将指定的元素插入到此队列中。 
        while (!q.isEmpty()) {
            u = q.poll();
            v = q.poll();//队列不为空的情况下,将队列中的值拿出来作比较
            if (u == null && v == null) {
                continue;//两个点都是空,那么不做比较
            }
            if ((u == null || v == null) || (u.val != v.val)) {
                return false;//如果其中一个结点是空,或者值不相同(不存在同时为空,前面判断过了),那么就说明不对称,返回false
            }
            //如果前面满足,说明对称,那么我们就往下继续判断他们的子节点,按照u.left,v.right,u.right,v.left的顺序放入,
            //这样取的时候是两两挨着取出来作比较的
            q.offer(u.left);
            q.offer(v.right);

            q.offer(u.right);
            q.offer(v.left);
        }
        return true;//当队列为空的那一步执行到这里,说明是树遍历完成且没有不对称的情况导致return false;说明是对称的,返回true
    }
}
*/
//上面的迭代方法,第一次是将两个根节点放进去,这样就多了一次迭代
//其实可以不去判断根节点,直接判断他的两个子树就好,但是要加上一个根节点为空的判断不为空才继续进行
//题目其实直接给了结点数目为1到1000,所以其实可以不用判断根节点为空的,
// 直接将代码q.offer(u);
//         q.offer(v);改作q.offer(root.left);
//                       q.offer(root.right);

6.收获

  • 直接中序遍历,比较数组是否对称可行吗?不可行,比如[1,2,2,2,null,2]这个中序遍历后是[2,2,1,2,2]但是树不对称。有个大哥给了一个想法,是对null做特殊操作,把这个null都改成层数的负值,虽然可能会跟对应的val同值,但是对付测试用例他成功了,所以处理好结点为空的情况,还是有使用中序遍历的可能的
  • 迭代一般都可以与递归互相切换,但是不一定哪个更加的简洁
  • 引入队列或者栈的方式,是将递归改成迭代的一种常见思路,递归其实隐藏了一个栈或队列,来存储一些递归的信息,所以我们自己用栈或队列来模拟这种过程
  • 感觉这些题目除了基本的处理思路之外,就是要多结合树啊,链表,队列等结构进行处理,最好可以先自己用思路捋顺,然后再用数据结构去实现
  • 这题跟100题判断两棵树是否相同很相似,对称与相等的区别我觉得也就是进入下一层递归时,两棵子树A、B的左右子树顺序换一下就行了
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值