Leetcode 101:对称二叉树(心路历程)

题目描述

在这里插入图片描述

思路分析

这个题拿到手上,第一个思考的就是:如何正确的去解读“镜像对称”。第一个想法就是:既然每个形态不同的树,中序遍历结果不同,那么直接对树进行中序遍历,然后比较数组是否对称即可。
如上述问题描述中,第一个例子的中序遍历为:【3,2,4,1,4,2,3】,显然以中点对称。
第二个例子的中序遍历为:【2,3,1,2,3】,那么无法满足要求。
正当我兴高采烈地秒完中序遍历直接提交时,出错了。。。
在这里插入图片描述

当面对这个树时,中序遍历结果是对称的。

思路二

究其原因,是由于中序遍历结果把 null 忽略掉没有记录。
假如上面这个树的输出为:【2,2,n,1,2,2,n】,那么轻松的就可以判定这也不是对称的。
然而,如何在递归过程中写出,能够记录 null 的代码,我没有能够实现。因为递归就是靠 null 来判断边界的,我没法去利用这个值。

思路三

看完答案后,发觉是自己把自己的思路禁锢住了。

既然要判断对称,那么要求便是:左子树与右子树对称。
对称的要求是:
1. 左子树的左孩子等于右子树的右孩子
2. 左子树的右孩子等于右子树的左孩子

边界条件:
1 . 左子树与右子树同时为空
2 . 左右子树有一者为空
3 . 左右子树值不相同

显然,要求是收敛的,存在边界,那么可以写新的递归,递归参数即为左右子树根

public class Solution2 {
    public boolean isSymmetric(TreeNode root) {
        if (root == null) return true;
        return isEqual(root.left, root.right);
    }

    public boolean isEqual(TreeNode left, TreeNode right) {
        if (left == null && right == null) return true;
        if (left == null || right == null) return false;
        if (left.val != right.val) return false;

        boolean re1 = isEqual(left.left, right.right);
        boolean re2 = isEqual(left.right, right.left);
        return re1 && re2;
    }
}

思路四

非递归写法,直接借用一个容器,来存储左右子树对应位置的节点。结束循环的边界即为:容器为空—树遍历结束。

public class Solution3 {
    public boolean isSymmetric(TreeNode root) {
        if (root == null) return true;
        if (root.left == null && root.right == null) return true;

        Stack<TreeNode> stack = new Stack<>();
        stack.push(root.left);
        stack.push(root.right);
        while (!stack.isEmpty()) {
            TreeNode left = stack.pop();
            TreeNode right = stack.pop();
            if (left == null && right == null) {
                continue;
            }
            if (left == null || right == null) {
                return false;
            }
            if (left.val != right.val) {
                return false;
            }
            stack.add(left.left);
            stack.add(right.right);
            stack.add(left.right);
            stack.add(right.left);

        }

        return true;
    }
}

不一定要用栈,队列也可以。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值