描述

题目描述

请实现一个函数,用来判断一棵二叉树是不是对称的。注意,如果一个二叉树同此二叉树的镜像是同样的,定义其为对称的。

示例
输入:{8,6,6,5,7,7,5}
返回值:true

知识点:二叉树
难度:⭐⭐⭐⭐


题解

解题思路

因为要比较左右结点是否对称,因此可以通过BFS每次对一层的结点进行遍历并比较是否对称。

对于树的问题,往往还可以通过递归解决,相对于遍历,代码量会少很多,但没有遍历容易理解。

方法一:BFS 广度优先遍历

图解

image-20210706224823557

算法流程:
  • 1、每次往队列中按顺序,从左到右放入当前结点的左右子节点,随后进行判断。

    2、每次从Queue中获取前两个元素,并比较值

    3、如果又一对元素比较结果不相等,则表示不对称。

    4、注意放入队列的顺序,左子结点的左子结点、右子结点的右子结点、左结点的右子结点、右结点的左子结点放入队列。

Java 版本代码如下:
import java.util.*;
public class Solution {
    boolean isSymmetrical(TreeNode pRoot) {
        if(pRoot == null) {
            return true;
        }
        return bfs(pRoot);
    }

    boolean bfs(TreeNode root) {
        if(root == null) {
            return true;
        }
        // BFS通常借助队列实现
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root.left);
        queue.offer(root.right);

        while(!queue.isEmpty()) {
            TreeNode left = queue.poll();
            TreeNode right = queue.poll();
            // 表示bfs已经进行到叶子结点了,
            if(left == null && right == null) {
                continue;                
            }
            // 判断是否对称
            if(left == null || right == null || left.val != right.val) {
                return false;                
            }
            // 对下一层的每个结点,都放入队列中
            // 注意放入队列的顺序,左子结点的左子结点、右子结点的右子结点、左结点的右子结点、右结点的左子结点放入队列。
            queue.offer(left.left);
            queue.offer(right.right);
            queue.offer(right.left);
            queue.offer(left.right);
        }
        return true;        
    }
}
复杂度分析:

时间复杂度 O(N):对每一层的左右对称两个结点都要进行比较
空间复杂度 O(N):需要借助队列实现BFS

方法二:递归

对于递归方法,最重要的是能清晰地定义递归函数的功能并实现,而且只需要在调用递归函数的时候直接使用该功能即可,不能跳入递归逻辑当中,只需要认准 ”调用即实现“ 即可。

算法流程:
  • 构建递归函数:
    • 定义函数功能:判断左右两个结点是否对称相等
    • 递归终止条件:
      • 没有子节点,说明当前结点是叶子结点
      • 没有右子节点(因为是按从左到右的顺序比较的)
      • 左右结点不对称
Java 版本代码如下:
public class Solution {
    boolean isSymmetrical(TreeNode pRoot)
    {
        if(pRoot == null){
            return true;
        }
        // 递归调用
        return recur(pRoot.left, pRoot.right);
    }

    // 递归函数功能:判断左右两个结点是否对称相等
    private boolean recur(TreeNode left, TreeNode right) {
        // 没有子节点,说明当前结点是叶子结点
        if(left == null) {
            return right == null;
        }
        // 没有右子节点
        if(right == null) {
            return false;
        }
        // 左右结点不对称
        if(left.val != right.val) {
            return false;
        } 
        // 左子树的右子树和右子树的左子树相同即可
        return recur(left.right, right.left) && recur(left.left, right.right);
    }
}
复杂度分析:

时间复杂度 O(N):递归次数平均为节点数
空间复杂度 O(N):最坏情况下,二叉树退化为链表