美文网首页
给定两二叉树,判断该两树是否对称?

给定两二叉树,判断该两树是否对称?

作者: android_hcf | 来源:发表于2020-04-18 14:49 被阅读0次

    如下图即为两树对称:


    图1.png

    对于树的遍历,一般想到的解法有两种,递归或者使用非递归的解法。
    对于该题而言,无论是哪种解法,每执行一步,均要判断该树的节点是否和对应数的反方向节点是否一致,如果不一致直接返回false,否则继续执行下一步。

    一,递归解法

    private static boolean isSymmetricTree(TreeNode node1, TreeNode node2) {
            if (node1 == null && node2 == null) return true;
            if (node1 == null && node2 != null) return false;
            if (node1 != null && node2 == null) return false;
            if (node1.value != node2.value) return false;
            return isSymmetricTree(node1.left, node2.right) && isSymmetricTree(node1.right, node2.left);
        }
    

    二,非递归解法

    1,O(n)空间复杂度的解法

    一般的,常规非递归解法,需要引入额外空间集合用于存放当前临时变量,不断遍历该集合直至为空,执行结束。
    对于该题而言,由于是两棵树,一棵是先根遍历,另外一棵就对应反向先根遍历,即先右,再根,再左的顺序。如何保证每次循环都保证是指定索引节点的判断,而且保证对应数的遍历顺序呢?由于每次都是1对的比较,则每次比较前集合均只应该存一对数据,即可用的数据结构可以是队列,也可以是堆栈。如下以队列举例:


    图2.png
    // 非递归O(n)空间复杂度的解法
    private static boolean isSymmetricTyeeByDeque(TreeNode root1, TreeNode root2) {
        LinkedList<TreeNode> list = new LinkedList<>();
        list.add(root1);
        list.add(root2);
        while(!list.isEmpty()) {
            TreeNode node1 = list.pop();
            TreeNode node2 = list.pop();
            // null判断主要是用于root的判断
            if (node1 == null && node2 == null) return true;
            if (node1 == null && node2 != null) return false;
            if (node1 != null && node2 == null) return false;
            if (node1.value != node2.value) return false;
                
            if(node1.left != null) {                
                list.add(node1.left);
            }
            if (node2.right != null) {              
                list.add(node2.right);
            }
                
            if (node1.right != null) {
                list.add(node1.right);
            }
            if (node2.left != null) {
                list.add(node2.left);
            }
        }
        return true;
    }
    
    2,O(1)空间复杂度的解法

    如何才能保证在不引入其他额外空间的情况下判断两树是否对称?这里我首先想到的就是Morris算法了。其思想就是,每次遍历,便查找当前节点是否有前驱节点,并且前驱节点是否指向了自己,如果没有指向自己,便指向自己,并且指针左子树下移,否则断开前驱节点与自己的联系,指针下移到右子树,以达到遍历整棵树的目的。还是画一个及其简单的效果图吧...


    Morris效果图.png
    // O(1)空间复杂度解法
    private static boolean isSymmetricByMorris(TreeNode root1, TreeNode root2) {
        TreeNode cur1 = root1;
        TreeNode cur2 = root2;
        while(cur1 != null || cur2 != null) {
            if (cur1 == null && cur2 == null) return true;
            if (cur1 == null && cur2 != null) return false;
            if (cur1 != null && cur2 == null) return false;
            if (cur1.value != cur2.value) return false;
                
            // 获取左子树下一节点,cur获取方向从左至右
            if (cur1.left != null) {
                TreeNode symmPreNode = getSymmPreNode(cur1);
                if (symmPreNode.right != cur1) {                    
                    symmPreNode.right = cur1;
                    cur1 = cur1.left;
                } else {
                    symmPreNode.right = null;
                    cur1 = cur1.right;
                }
            } else {
                cur1 = cur1.right;
            }
            if (cur1 != null) {             
                System.out.println(cur1.value);
            }
                
            // 获取右子树下一节点,,cur获取方向从右至左
            if (cur2.right != null) {
                TreeNode symmNextNode = getSymmNextNode(cur2);
                if (symmNextNode.left == cur2) {
                    symmNextNode.left = null;
                    cur2 = cur2.left;
                } else {
                    symmNextNode.left = cur2;
                    cur2 = cur2.right;
                }
            } else {
                cur2 = cur2.left;
            }
            if (cur2 != null) {
                System.out.println(cur2.value);
            }
            System.out.println("----------------------");
        }
        return true;
    }
        
    // 获取当前节点的前驱节点,由于该方法之外已判断node不为null,故这里不用再做判断
    private static TreeNode getSymmPreNode(TreeNode node) {
        TreeNode tn = node.left;
        while(tn.right != null && tn.right != node) {
            tn = tn.right;
        }
        return tn;
    }
    

    下面再给出当前我的测试用例

    public class TreeNode {
    
        public int value;
        public TreeNode left;
        public TreeNode right;
        
        public TreeNode(int value) {
            this.value = value;
        }
        
        public TreeNode(int value, TreeNode left, TreeNode right) {
            this.value = value;
            this.left = left;
            this.right = right;
        }
    }
    
    public static void main(String[] args) {
        TreeNode node16 = new TreeNode(16);
        TreeNode node18 = new TreeNode(18);
        TreeNode node19 = new TreeNode(19, node18, null);
        TreeNode node17 = new TreeNode(17);
        TreeNode node23 = new TreeNode(23);
        TreeNode node22 = new TreeNode(22, node17, node23);
        TreeNode node21 = new TreeNode(21, node16, node19);
        TreeNode node20 = new TreeNode(20, node21, node22);
            
        TreeNode node16$ = new TreeNode(16);
        TreeNode node18$ = new TreeNode(18);
        TreeNode node19$ = new TreeNode(19, null, node18$);
        TreeNode node17$ = new TreeNode(17);
        TreeNode node23$ = new TreeNode(23);
        TreeNode node22$ = new TreeNode(22, node23$, node17$);
        TreeNode node21$ = new TreeNode(21, node19$, node16$);
        TreeNode node20$ = new TreeNode(20, node22$, node21$);
    
        //  System.out.println(isSymmetricTree(node20, node20$));
        //  System.out.println(isSymmetricTyeeByDeque(node20, node20$));
        System.out.println(isSymmetricByMorris(node20, node20$));
        }
    

    平时在练习过程中,随着练习的增多,代码也随之增大,删之可惜,本文所写纯粹是为记录点滴的需要,如有雷同纯属巧合。

    相关文章

      网友评论

          本文标题:给定两二叉树,判断该两树是否对称?

          本文链接:https://www.haomeiwen.com/subject/giamvhtx.html