代码随想录算法训练营第十五天 | 层序遍历 、226.翻转二叉树、101.对称二叉树

层序遍历

题目链接:
学会二叉树的层序遍历,可以一口气打完以下十题:

文档讲解:https://programmercarl.com/0102.%E4%BA%8C%E5%8F%89%E6%A0%91%E7%9A%84%E5%B1%82%E5%BA%8F%E9%81%8D%E5%8E%86.html
视频讲解:https://www.bilibili.com/video/BV1GY4y1u7b2

思路(层序遍历)

使用队列来辅助遍历。记录每一层的个数,然后弹出一个节点,就把他的左右孩子放进队列中。当这一层的个数为0,就开始遍历下一行。

代码

102.二叉树的层序遍历

class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {
        List<List<Integer>> res = new ArrayList<>();
        if (root == null) return res;
        Deque<TreeNode> deque = new LinkedList<>();
        deque.push(root);
        while (!deque.isEmpty()) {
            List<Integer> temp = new ArrayList<>();
            int size = deque.size();
            while(size-- > 0) {
                TreeNode cur = deque.pollFirst();
                temp.add(cur.val);
                if (cur.left != null) deque.addLast(cur.left);
                if (cur.right != null) deque.addLast(cur.right);
            }
            res.add(temp);
        }
        return res;
    }
}

107.二叉树的层次遍历 II

class Solution {
    public List<List<Integer>> levelOrderBottom(TreeNode root) {
        List<List<Integer>> res = new ArrayList<>();
        if (root == null) return res;
        Deque<TreeNode> deque = new LinkedList<>();
        deque.addLast(root);
        while (!deque.isEmpty()) {
            int size = deque.size();
            List<Integer> temp = new ArrayList<>();
            while (size-- > 0) {
                TreeNode node = deque.pollFirst();
                temp.add(node.val);
                if (node.left != null) deque.addLast(node.left);
                if (node.right != null) deque.addLast(node.right);
            }
            res.add(temp);
        }
        Collections.reverse(res); // 翻转数组
        return res;
    }
}

199.二叉树的右视图

class Solution {
    public List<Integer> rightSideView(TreeNode root) {
        List<Integer> res = new ArrayList<>();
        if (root == null) return res;
        Deque<TreeNode> deque = new LinkedList<>();
        deque.addLast(root);
        while (!deque.isEmpty()) {
            int size = deque.size();
            while (size-- > 0) {
                TreeNode node = deque.pollFirst();
                if (node.left != null) deque.addLast(node.left);
                if (node.right != null) deque.addLast(node.right);
                if (size == 0) res.add(node.val); // 遍历到本层最后一个节点再放入数组中
            }
        }

        return res;
    }
}

637.二叉树的层平均值

class Solution {
    public List<Double> averageOfLevels(TreeNode root) {
        List<Double> res = new ArrayList<>();
        Deque<TreeNode> deque = new LinkedList<>();
        deque.addLast(root);
        while (!deque.isEmpty()) {
            int size = deque.size();
            int size2 = deque.size();
            Double sum = 0D;
            while (size-- > 0) {
                TreeNode node = deque.pollFirst();
                sum += node.val;
                if (node.left != null) deque.addLast(node.left);
                if (node.right != null) deque.addLast(node.right);
            }
            res.add(sum / size2);
        }
        return res;
    }
}

429.N叉树的层序遍历

class Solution {
    public List<List<Integer>> levelOrder(Node root) {
        List<List<Integer>> res = new ArrayList<>();
        if (root == null) return res;
        Deque<Node> deque = new LinkedList<>();
        deque.addLast(root);
        while(!deque.isEmpty()) {
            int size = deque.size();
            List<Integer> temp = new ArrayList<>();
            while (size-- > 0) {
                Node node = deque.pollFirst();
                temp.add(node.val);
                for (Node child : node.children) { // 这里放入孩子节点的list,而不是左孩子和右孩子
                    deque.addLast(child);
                }
            }
            res.add(temp);
        }
        return res;
    }
}

515.在每个树行中找最大值

class Solution {
    public List<Integer> largestValues(TreeNode root) {
        List<Integer> res = new ArrayList<>();
        if (root == null) return res;
        Deque<TreeNode> deque = new LinkedList<>();
        deque.addLast(root);
        while (!deque.isEmpty()) {
            int size = deque.size();
            int max = Integer.MIN_VALUE;
            while (size-- > 0) {
                TreeNode node = deque.pollFirst();
                max = Math.max(max, node.val);
                if (node.left != null) deque.addLast(node.left);
                if (node.right != null) deque.addLast(node.right);
            }
            res.add(max);
        }
        return res;
    }
}

116.填充每个节点的下一个右侧节点指针

class Solution {
    public Node connect(Node root) {
        if (root == null) return root;
        Deque<Node> deque = new LinkedList<>();
        deque.addLast(root);
        while (!deque.isEmpty()) {
            int size = deque.size();
            while (size-- > 0) {
                Node node1 = deque.pollFirst();
                Node node2 = deque.peekFirst(); // 获得下一个节点的信息
                if (size == 0) node1.next = null;
                else node1.next = node2;
                if (node1.left != null) deque.addLast(node1.left);
                if (node1.right != null) deque.addLast(node1.right);
            }
        }
        return root;
    }
}

117.填充每个节点的下一个右侧节点指针II

这道题目说是二叉树,上面的116题目说是完整二叉树,116的代码有判断左右孩子是否为空,所以这道题代码和116是一样的。

104.二叉树的最大深度

class Solution {
    public int maxDepth(TreeNode root) {
        int res = 0;
        if (root == null) return res;
        Deque<TreeNode> deque = new LinkedList<>();
        deque.addLast(root);
        while (!deque.isEmpty()) {
            int size = deque.size();
            while (size-- > 0) {
                TreeNode node = deque.pollFirst();
                if (node.left != null) deque.addLast(node.left);
                if (node.right != null) deque.addLast(node.right);
            }
            res++;
        }
        return res;
    }
}

111.二叉树的最小深度

class Solution {
    public int minDepth(TreeNode root) {
        int depth = 0;
        if (root == null) return depth;
        Deque<TreeNode> deque = new LinkedList<>();
        deque.addLast(root);
        while (!deque.isEmpty()) {
            int size = deque.size();
            while (size-- > 0) {
                TreeNode node = deque.pollFirst();
                if (node.left != null) deque.addLast(node.left);
                if (node.right != null) deque.addLast(node.right);
                if (node.left == null && node.right == null) return depth + 1; // 当左右孩子都为空,直接返回最小深度
            }
            depth++;
        }
        return depth;
    }
}

226.翻转二叉树

题目链接:https://leetcode.cn/problems/invert-binary-tree/
文档讲解:https://programmercarl.com/0226.%E7%BF%BB%E8%BD%AC%E4%BA%8C%E5%8F%89%E6%A0%91.html#%E7%AE%97%E6%B3%95%E5%85%AC%E5%BC%80%E8%AF%BE
视频讲解:https://www.bilibili.com/video/BV1sP4y1f7q7

思路

  1. 确定递归函数的参数和返回值。
    参数就是要传入节点的指针,不需要其他参数了,通常此时定下来主要参数,如果在写递归的逻辑中发现还需要其他参数的时候,随时补充。
    返回值的话其实也不需要,但是题目中给出的要返回root节点的指针,可以直接使用题目定义好的函数,所以就函数的返回类型为TreeNode。
public TreeNode invertTree(TreeNode root)
  1. 确定终止条件。
    当前节点为空的时候,就返回。
if (root == null) return root;
  1. 确定单层递归的逻辑。
// 因为是前序遍历,所以先进行交换左右孩子节点,然后反转左子树,反转右子树。
swapChildren(root);
invertTree(root.left);
invertTree(root.right);

// 后序遍历就交换一下顺序。
swapChildren(root);
invertTree(root.left);
invertTree(root.right);

// 如果是中序遍历,是左-中-左,如果是左中右的话,翻转的右孩子就是之前翻转过来的左孩子。
invertTree(root.left);
swapChildren(root);
invertTree(root.left);

代码

class Solution {
    public TreeNode invertTree(TreeNode root) {
        if (root == null) return root;
        swapChildren(root);
        invertTree(root.left);
        invertTree(root.right);
        return root;
    }
    public void swapChildren(TreeNode root) {
        TreeNode temp = root.left;
        root.left = root.right;
        root.right = temp;
    }
}

101.对称二叉树

题目链接:https://leetcode.cn/problems/symmetric-tree/
文档讲解:https://programmercarl.com/0101.%E5%AF%B9%E7%A7%B0%E4%BA%8C%E5%8F%89%E6%A0%91.html#%E7%AE%97%E6%B3%95%E5%85%AC%E5%BC%80%E8%AF%BE
视频讲解:https://www.bilibili.com/video/BV1ue4y1Y7Mf

思路

这道题只能用后序遍历,因为需要得到左右子树是否对称以后,返回给中间节点。

  1. 确定递归函数的参数和返回值。
    因为我们要比较的是根节点的两个子树是否是相互翻转的,进而判断这个树是不是对称树,所以要比较的是两个树,参数自然也是左子树节点和右子树节点。返回值自然是boolean类型。
boolean compare(TreeNode left, TreeNode right)
  1. 确定终止条件。
    要比较两个节点数值相不相同,首先要把两个节点为空的情况弄清楚,否则后面比较数值的时候就会操作空指针了。

节点为空的情况有:

  • 左节点为空,右节点不为空,不对称,return false
  • 左不为空,右为空,不对称 return false
  • 左右都为空,对称,返回true

此时已经排除掉了节点为空的情况,那么剩下的就是左右节点不为空:

  • 左右都不为空,比较节点数值,不相同就return false
  • 此时左右节点不为空,且数值也不相同的情况我们也处理了。
if (left == null && right == null) return true;
else if (left == null && right != null) return false;
else if (left != null && right == null) return false;
else if (left.val != right.val) return false;

注意上面最后一种情况,没有使用else,而是else if, 因为我们把以上情况都排除之后,剩下的就是左右节点都不为空,且数值相同的情况。

  1. 确定单层递归的逻辑
    此时才进入单层递归的逻辑,单层递归的逻辑就是处理 左右节点都不为空,且数值相同的情况。
    比较二叉树外侧是否对称:传入的是左节点的左孩子,右节点的右孩子。
    比较内侧是否对称,传入左节点的右孩子,右节点的左孩子。
    如果左右都对称就返回true ,有一侧不对称就返回false 。
boolean outside = compare(left.left, right.right);
boolean inside = compare(left.right, right.left);
boolean res = outside && inside;
return res;

代码

class Solution {
    public boolean isSymmetric(TreeNode root) {
        return compare(root.left, root.right);
    }

    public boolean compare(TreeNode left, TreeNode right) {
        if (left == null && right == null) return true;
        else if (left == null && right != null) return false;
        else if (left != null && right == null) return false;
        else if (left.val != right.val) return false;
        boolean outside = compare(left.left, right.right);
        boolean inside = compare(left.right, right.left);
        boolean res = outside && inside;
        return res;
    }
}
  • 36
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值