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

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

      1
     / \
    2   2
   / \ / \
  3  4 4  3

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

     1
    / \
    2   2
    \   \
    3    3

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/symmetric-tree 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

题解:

该题还是考察对树结构的遍历,判断一棵树是否是对称的树,从大的方面来看(从根节点来看), 需要判断左子树是否与右子树是否为对称的树即可。从子树上看,例如例1中的第二层的2号节点和3号节点(根节点为第一层,往下增长,从每层的左边开始标号) 只需要判断2号节点的左子树与3号节点的右子树是否相同,2号节点的右子树与3号节点的左子树是否相同。 从子树开始就可以利用递归对子树的对称性进行判断。 直接使用递归的方法需要考虑栈的深度,如果树的深度大于了栈的深度,需要考虑使用辅助结构来迭代遍历。

使用递归的解法

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public boolean isSymmetric(TreeNode root) {
        if(root ==  null) {
            return true;
        } else {
            return isSymmetric(root.left,root.right);
        }
    }
private boolean isSymmetric(TreeNode left,TreeNode right) {
    if(left == null &&  right == null) {
        return true;
    } else if (left == null || right == null) {
        return false;
    }
    if(left.val == right.val) {
        // 检查左子树的左子树与右子树的右子树是否一致
        return isSymmetric(left.left,right.right) 
        // 检查左子树的右子树与右子树的左子树是否一致
        && isSymmetric(left.right,right.left);
    }
    return false;
}

}

使用迭代的方式的解法

解法其实与递归的逻辑是一致的,只是相对于递归自己实现了栈的处理。此处用了两个栈,主要是为了进行隔离左子树和右子树的节点,避免混淆,用一个栈或者用一个队列都是可以实现的

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public boolean isSymmetric(TreeNode root) {
        if(root ==  null) {
            return true;
        }
        //新建两个栈结构存储左子树的节点和右子树节点
        Stack<TreeNode> leftStack = new Stack();
        Stack<TreeNode> rightStack = new Stack();
        // 先将左右子树的节点根节点入栈
        leftStack.push(root.left);
        rightStack.push(root.right);
        while(!leftStack.empty() && !rightStack.empty()) {
            // 取出节点,并进行值判断
            TreeNode left = leftStack.pop();
            TreeNode right = rightStack.pop();
            if(left == null && right == null) {
                continue;
            } else if(left == null || right == null) {
                return false;
            }
            if(left.val == right.val) {
                // 将子节点压栈
                // 左子树先压右孩子,然后左孩子
                leftStack.push(left.right);
                leftStack.push(left.left);
                // 右子树先压左孩子,然后右孩子
                rightStack.push(right.left);
                rightStack.push(right.right);
            }else {
                return false;
            }
        }
        return true;
    }
}