代码随想录刷题Day18

67 阅读4分钟

二叉树的广度优先遍历BFS

BFS 遍历使用队列数据结构:

void bfs(TreeNode root) {
    Queue<TreeNode> queue = new ArrayDeque<>();
    queue.add(root);
    while (!queue.isEmpty()) {
        TreeNode node = queue.poll(); // Java 的 pop 写作 poll()
        if (node.left != null) {
            queue.add(node.left);
        }
        if (node.right != null) {
            queue.add(node.right);
        }
    }
}
  1. 102. 二叉树的层序遍历

层序遍历要求我们区分每一层,也就是返回一个二维数组。而 BFS 的遍历结果是一个一维数组,无法区分每一层。

image.png

    public List<List<Integer>> levelOrder(TreeNode root) {
        List<List<Integer>> res =new ArrayList<>();//题目要求的是一个二维数组
        Queue<TreeNode> queue = new ArrayDeque<>();
        if(root!=null){
            queue.add(root);
        }
        // while 循环的每一轮中,都是将当前层的所有结点出队列,再将下一层的所有结点入队列
        while(!queue.isEmpty()){
            int n=queue.size();//记录队列中的节点数量n
            List<Integer> level =new ArrayList<>();//记录每一层的节点
            for(int i=0;i<n;i++){// 变量 i 无实际意义,只是为了循环 n 次
                TreeNode node = queue.poll();
                level.add(node.val);//把当前层节点值加入level中
                if(node.left!=null){
                    queue.add(node.left);
                }
                if(node.right!=null){
                    queue.add(node.right);
                }
            }
            res.add(level);
        }
        return res;
    }
}
  1. 107. 二叉树的层序遍历 II
  • 思路和上一题一样,最后反转
    public List<List<Integer>> levelOrderBottom(TreeNode root) {
        List<List<Integer>> res =new ArrayList<>();//题目要求的是一个二维数组
        Queue<TreeNode> queue = new ArrayDeque<>();
        if(root!=null){
            queue.add(root);
        }
        // while 循环的每一轮中,都是将当前层的所有结点出队列,再将下一层的所有结点入队列
        while(!queue.isEmpty()){
            int n=queue.size();//记录队列中的节点数量n
            List<Integer> level =new ArrayList<>();//记录每一层的节点
            for(int i=0;i<n;i++){// 变量 i 无实际意义,只是为了循环 n 次
                TreeNode node = queue.poll();
                level.add(node.val);//把当前层节点值加入level中
                if(node.left!=null){
                    queue.add(node.left);
                }
                if(node.right!=null){
                    queue.add(node.right);
                }
            }
            res.add(level);
        }
        Collections.reverse(res);//反转
        return res;
    }
}
  1. 199. 二叉树的右视图
  • 关键是记录每层最后一个节点
    public List<Integer> rightSideView(TreeNode root) {
        List<Integer> res =new ArrayList<>();
        Queue<TreeNode> queue = new ArrayDeque<>();
        if(root!=null){
            queue.add(root);
        }
        // while 循环的每一轮中,都是将当前层的所有结点出队列,再将下一层的所有结点入队列
        while(!queue.isEmpty()){
            int n=queue.size();//记录队列中的节点数量n
            for(int i=0;i<n;i++){// 变量 i 无实际意义,只是为了循环 n 次
                TreeNode node = queue.poll();
                if(i==n-1){//遍历到当前层最后一个节点时,把节点值加入res
                    res.add(node.val);
                }
                if(node.left!=null){
                    queue.add(node.left);
                }
                if(node.right!=null){
                    queue.add(node.right);
                }
            }
        }
        return res;
    }
}
  1. 637. 二叉树的层平均值
    public List<Double> averageOfLevels(TreeNode root) {
        List<Double> res = new ArrayList<>();
        Queue<TreeNode> queue = new ArrayDeque<>();
        if(root!=null){
            queue.add(root);
        }
        while(!queue.isEmpty()){
            int n=queue.size();
            Double s=0.0;//要注意类型,不然最后会报错
            for(int i=0;i<n;i++){
                TreeNode node = queue.poll();
                s+=node.val;
                if(node.left!=null){
                    queue.add(node.left);
                }
                if(node.right!=null){
                    queue.add(node.right);
                }
            }
            res.add(s/n);
        }
        return res;
    }
}
  1. 429. N 叉树的层序遍历
  • 关键在于遍历children节点
class Solution {
    public List<List<Integer>> levelOrder(Node root) {
        List<List<Integer>> res =new ArrayList<>();//题目要求的是一个二维数组
        Queue<Node> queue = new ArrayDeque<>();
        if(root!=null){
            queue.add(root);
        }
        // while 循环的每一轮中,都是将当前层的所有结点出队列,再将下一层的所有结点入队列
        while(!queue.isEmpty()){
            int n=queue.size();//记录队列中的节点数量n
            List<Integer> level =new ArrayList<>();//记录每一层的节点
            for(int i=0;i<n;i++){// 变量 i 无实际意义,只是为了循环 n 次
                Node node = queue.poll();
                level.add(node.val);//把当前层节点值加入level中
                for(Node child:node.children){//遍历node的子节点,加入队列
                    queue.add(child);
                }
            }
            res.add(level);
        }
        return res;
    }
}
  1. 515. 在每个树行中找最大值
    public List<Integer> largestValues(TreeNode root) {
        List<Integer> res =new ArrayList<>();
        Queue<TreeNode> queue = new ArrayDeque<>();
        if(root!=null){
            queue.add(root);
        }
        // while 循环的每一轮中,都是将当前层的所有结点出队列,再将下一层的所有结点入队列
        while(!queue.isEmpty()){
            int n=queue.size();//记录队列中的节点数量n
            List<Integer> level =new ArrayList<>();//记录每一层的节点
            for(int i=0;i<n;i++){// 变量 i 无实际意义,只是为了循环 n 次
                TreeNode node = queue.poll();
                level.add(node.val);//把当前层节点值加入level中
                if(node.left!=null){
                    queue.add(node.left);
                }
                if(node.right!=null){
                    queue.add(node.right);
                }
            }
            res.add(Collections.max(level));
        }
        return res;
    }
}

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

  • 这两题一个是完美二叉树,一个是普通二叉树,解法都一样
    public Node connect(Node root) {
        if(root==null){
            return root;
        }
        Queue<Node> queue = new ArrayDeque<>(); 
        queue.add(root);
        while(!queue.isEmpty()){
            int n=queue.size();
            for(int i=0;i<n;i++){
                Node node=queue.poll();
                if(i<n-1){
                    node.next=queue.peek();
                }
                if(node.left!=null){
                    queue.add(node.left);
                }
                if(node.right!=null){
                    queue.add(node.right);
                }
            }
        }
        return root;
    }
}
  1. 104. 二叉树的最大深度
    public int maxDepth(TreeNode root) {
        int maxDepth=0;
        Queue<TreeNode> queue = new ArrayDeque<>();
        if(root!=null){
            queue.add(root);
        }
        // while 循环的每一轮中,都是将当前层的所有结点出队列,再将下一层的所有结点入队列
        while(!queue.isEmpty()){
            int n=queue.size();//记录队列中的节点数量n
            for(int i=0;i<n;i++){// 变量 i 无实际意义,只是为了循环 n 次
                TreeNode node = queue.poll();
                if(node.left!=null){
                    queue.add(node.left);
                }
                if(node.right!=null){
                    queue.add(node.right);
                }
            }
            maxDepth++;
        }
        return maxDepth;
    }
}
  1. 111. 二叉树的最小深度
  • 返回遇到第一个叶子节点时的深度最快捷
    public int minDepth(TreeNode root) {
        int minDepth=0;
        Queue<TreeNode> queue = new ArrayDeque<>();
        if(root!=null){
            queue.add(root);
        }
        // while 循环的每一轮中,都是将当前层的所有结点出队列,再将下一层的所有结点入队列
        while(!queue.isEmpty()){
            int n=queue.size();//记录队列中的节点数量n
            minDepth++;//深度+1
            for(int i=0;i<n;i++){// 变量 i 无实际意义,只是为了循环 n 次
                TreeNode node = queue.poll();
                if(node.left==null&&node.right==null){//遇到第一个叶子节点就返回
                    return minDepth;
                }
                if(node.left!=null){
                    queue.add(node.left);
                }
                if(node.right!=null){
                    queue.add(node.right);
                }
            }
        }
        return minDepth;
    }
}