代码随想录算法训练营day15 | 102.二叉树的层序遍历 226.翻转二叉树 101. 对称二叉树

79 阅读4分钟

102.二叉树的层序遍历

给你二叉树的根节点 root ,返回其节点值的 层序遍历 。 (即逐层地,从左到右访问所有节点)。

  • 树中节点数目在范围 [0, 2000] 内
  • -1000 <= Node.val <= 1000

102. 二叉树的层序遍历 - 力扣(Leetcode)

思路

  1. root 为空,即节点数量为0,返回空数组。
  2. 否则,使用队列对二叉树进行遍历。将 root入队,将 null 作为每一层的分隔符入队。
    • 当队列中元素数量大于 2 时,进行循环
    • 在每一轮循环中,创建一个列表 list
      • 从队列中出队一个元素,
      • 若该元素不是 null,则将该元素的数值加入到 list
      • 依次判断该元素是否有左、右孩子,若有,则加入队列中;
      • 若该元素 null,则将 list 加入到结果中,在队列中插入一个分隔符 null
      • 结束本轮循环。

代码

/**
 * 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 List<List<Integer>> levelOrder(TreeNode root) {
        List<List<Integer>> res = new ArrayList<>();

        if(root == null){
            return res;
        }

        Deque<TreeNode> que = new LinkedList<>();

        TreeNode cur = null;

        que.add(root);
        que.add(null);

        do{
            List<Integer> list = new ArrayList<>();

            while((cur = que.poll()) != null){

                list.add(cur.val);

                if(cur.left != null){
                    que.add(cur.left);
                }

                if(cur.right != null){
                    que.add(cur.right);
                }
            }

            res.add(list);

            que.add(null);
            
        }while(que.size()>1);

        return res;

    }
}

226.翻转二叉树

给你一棵二叉树的根节点 root ,翻转这棵二叉树,并返回其根节点。

思路

使用二叉树深度遍历的任一种方法,当遍历到任一节点时,将具体操作替换成交换该节点的左右孩子节点。
交换节点的左右孩子节点时,只要该节点存在左孩子或右孩子,都可以进行交换,将 null也作为孩子进行交换可减少代码量。
使用二叉树广度遍历时,不需要区分每一层的元素,因此使用一个for循环即可,当队列为空时结束循环。

代码

深度遍历的代码如下:

/**
 * 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 TreeNode invertTree(TreeNode root) {
        invert(root);

        return root;
    }

    private void invert(TreeNode cur){
        if(cur == null){
            return;
        }

        if(cur.left != null){
            invert(cur.left);
        }

        if(cur.right !=null){
            invert(cur.right);
        }

        swapChildren(cur);
    }

    private void swapChildren(TreeNode root){
        if(root.left != null || root.right != null){
            TreeNode tmp = root.left;
            root.left = root.right;
            root.right = tmp;
        }
    }
}

广度遍历的代码如下:

/**
 * 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 TreeNode invertTree(TreeNode root) {

        Deque<TreeNode> que = new LinkedList<>();

        if(root == null){
            return root;
        }

        TreeNode cur = null;

        que.add(root);

        while(!que.isEmpty()){
            cur = que.poll();

            if(cur.left != null){
                que.add(cur.left);
            }

            if(cur.right != null){
                que.add(cur.right);
            }

            swapChildren(cur);
        }

        return root;
    }


    private void swapChildren(TreeNode root){
        if(root.left != null || root.right != null){
            TreeNode tmp = root.left;
            root.left = root.right;
            root.right = tmp;
        }
    }
}

101. 对称二叉树

给你一个二叉树的根节点 root , 检查它是否轴对称

  • 树中节点数目在范围 [1, 1000] 内

101. 对称二叉树 - 力扣(Leetcode)

思路

对二叉树进行层序遍历。

  1. 判断根节点的情况
    • 如果根节点同时没有左右孩子节点,即二叉树只有根节点这一个节点,则该二叉树是对称的,返回 true
    • 否则,如果根节点没有左孩子或没有右孩子,(由于根节点同时没有左右孩子节点为假,即根节点不能同时没有左右孩子节点),则二叉树是不对称的,返回false
    • 否则,该二叉树的根节点同时拥有左右孩子,继续以下操作。
  2. 将根节点的左右孩子节点依次加入队列中,当队列不为空时,对二叉树的每一层进行循环。
    • 在一个循环中,先判断当前队列的size是否是双数,如果不是,返回false,这个操作可以确保之后出队时可以一次性出队2个元素,避免代码出错;而同样地,不满足这个特性的二叉树是不对称的。
    • 在队列中插入一个null,作为当前层与下一层之间的分隔符。
    • 进入循环,直到当前队列的队首元素为分隔符null为止,在一次循环中,
      • 依次出队两个元素fisrtsecond
      • 如果fisrtsecondval不相等,即这两个对称位置的元素不相同,二叉树不对称,返回false
      • 否则,判断fisrtsecond的孩子是否对称,包括外侧对称和内侧对称。
      • 外侧对称的节点是first.leftsecond.right,若这两个节点存在且值相等,将这两个节点入队;若这两个节点存在但值不相等,则不对称,返回false
      • 内侧对称的节点是first.rightsecond.left,若这两个节点存在且值相等,将这两个节点入队;若这两个节点存在但值不相等,则不对称,返回false
      • 这样的操作后,可以看到,对称位置的节点在队列中是相邻的,因此每次出队的fisrtsecond是对称位置的元素。
    • 本轮循环结束,去除分隔符。这一步一定要做,否则影响循环判断条件的结果和之后程序的运行。

代码

/**
 * 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.left == null && root.right == null){
            return true;
        }else if(root.left == null || root.right == null){
            return false;
        }

        Deque<TreeNode> que = new LinkedList<>();

        que.add(root.left);
        que.add(root.right);

        TreeNode first = null, second = null;

        do{

            if(que.size()%2 != 0){
                return false;
            }

            // 加入分隔符
            que.add(null);

            while(que.peek()!=null){

                first = que.poll();
                second = que.poll();

                if(first.val!=second.val){
                    return false;
                }

                // 外侧
                if(first.left != null && second.right != null){
                    if(first.left.val == second.right.val){
                        // 对称 且 非null
                        que.add(first.left);
                        que.add(second.right);
                    }else{
                        // 不对称 且 非null
                        return false;
                    }
                }else if(first.left != null || second.right != null){
                    // 有一个为null ,而另一个不为 null
                    return false;
                }

                // 内侧
                if(first.right != null && second.left !=null){
                    if(first.right.val == second.left.val){
                        // 对称 且 非null
                        que.add(first.right);
                        que.add(second.left);
                    }else{
                        return false;
                    }
                }else if(first.right !=null || second.left !=null){
                    return false;
                }
            }

            // 去除分隔符
            que.poll();

        }while(!que.isEmpty());

        return true;

    }
}