• 对称二叉树


    给定一个二叉树,检查它是否是镜像对称的。

    例如,二叉树 [1,2,2,3,4,4,3] 是对称的。

    但是下面这个[1,2,2,null,3,null,3],则不是镜像对称的:

    如果你可以运用递归和迭代两种方法解决这个问题,会很加分。

    解法一: 递归

    如果一个树的左子树与右子树镜像对称,那么这个树是对称的。

    因此,该问题可以转化为:两个树在什么情况下互为镜像?

    如果同时满足下面的条件,两个树互为镜像:

    1. 它们的两个根节点具有相同的值
    2. 每个树的右子树都与另一个树的左子树镜像对称

    就像人站在镜子前审视自己那样。镜中的反射与现实中的人具有相同的头部,但反射的右臂对应于人的左臂,反之亦然。

    上面的解释可以很自然地转换为一个递归函数,如下所示:

    swift方式

    public class TreeNode{
        public var val: Int
        public var left: TreeNode?
        public var right: TreeNode?
        public init(_ val: Int){
            self.val = val
            self.left = nil
            self.right = nil
        }
    }
    
    func isSymmetric(_ root: TreeNode?) -> Bool {
        return isMirror(root,root)
    }
    
    func isMirror(_ t1: TreeNode?, _ t2: TreeNode?) -> Bool{
        if t1 == nil && t2 == nil {
            return true
        }
        if t1 == nil || t2 == nil {
            return false
        }
        return (t1?.val == t2?.val) && isMirror(t1?.right, t2?.left) && isMirror(t1?.left, t2?.right)
    }

    复杂度分析:O(n)。n为树中结点的个数

    解法二:迭代

    我们可以换种思路,left子树是正常的先序遍历根节点 -> 左子树 -> 右子树 的顺序,对于right子树的话是根节点 -> 右子树 -> 左子树 的顺序。

    所以我们可以用栈,把递归改写为迭代的形式。

    public boolean isSymmetric(TreeNode root) { 
        if (root == null) {
            return true;
        }
        Stack<TreeNode> stackLeft = new Stack<>();
        Stack<TreeNode> stackRight = new Stack<>();
        TreeNode curLeft = root.left;
        TreeNode curRight = root.right;
        while (curLeft != null || !stackLeft.isEmpty() || curRight!=null || !stackRight.isEmpty()) {
            // 节点不为空一直压栈
            while (curLeft != null) {
                stackLeft.push(curLeft);
                curLeft = curLeft.left; // 考虑左子树
            }
            while (curRight != null) {
                stackRight.push(curRight);
                curRight = curRight.right; // 考虑右子树
            }
            //长度不同就返回 false
            if (stackLeft.size() != stackRight.size()) {
                return false;
            }
            // 节点为空,就出栈
            curLeft = stackLeft.pop();
            curRight = stackRight.pop();
    
            // 当前值判断
            if (curLeft.val != curRight.val) {
                return false;
            }
            // 考虑右子树
            curLeft = curLeft.right;
            curRight = curRight.left;
        }
        return true;
    }

    当然我们也可以使用中序遍历或者后序遍历,是一样的道理。

    解法三:BFS队列

    DFS 考虑完了,当然还有 BFS,一层一层的遍历两个树,然后判断对应的节点是否相等即可。利用两个队列来保存下一次遍历的节点即可。

    public boolean isSymmetric6(TreeNode root) {
        if (root == null) {
            return true;
        }
        Queue<TreeNode> leftTree = new LinkedList<>();
        Queue<TreeNode> rightTree = new LinkedList<>();
        //两个树的根节点分别加入
        leftTree.offer(root.left);
        rightTree.offer(root.right);
        while (!leftTree.isEmpty() && !rightTree.isEmpty()) {
            TreeNode curLeft = leftTree.poll();
            TreeNode curRight = rightTree.poll();
            if (curLeft == null && curRight != null || curLeft != null && curRight == null) {
                return false;
            }
            if (curLeft != null && curRight != null) {
                if (curLeft.val != curRight.val) {
                    return false;
                }
                //先加入左子树后加入右子树
                leftTree.offer(curLeft.left);
                leftTree.offer(curLeft.right);
                
                //先加入右子树后加入左子树
                rightTree.offer(curRight.right);
                rightTree.offer(curRight.left);
            }
    
        }
        if (!leftTree.isEmpty() || !rightTree.isEmpty()) {
            return false;
        }
        return true;
    }

    上面就是对称二叉树的几种解法,对于第二种,第三种使用到了栈与队列,大家可以了解思想,这个题目是个很不错的题目。希望对大家有所帮助

  • 相关阅读:
    “XXXXX” is damaged and can’t be opened. You should move it to the Trash 解决方案
    深入浅出 eBPF 安全项目 Tracee
    Unity3d开发的知名大型游戏案例
    Unity 3D 拥有强大的编辑界面
    Unity 3D物理引擎详解
    Unity 3D图形用户界面及常用控件
    Unity 3D的视图与相应的基础操作方法
    Unity Technologies 公司开发的三维游戏制作引擎——Unity 3D
    重学计算机
    windows cmd用户操作,添加,设备管理员组,允许修改密码
  • 原文地址:https://www.cnblogs.com/guohai-stronger/p/11762230.html
Copyright © 2020-2023  润新知