【LeetCode】广度优先搜索之层次遍历通用解体模板

#LeetCode每日一题【二叉树专题】

  • 经常涉及到一些二叉树跟层数相关的题目,例如需要对树每一层的节点做些逻辑处理、求层数(高度)等,类似于这类题目,都可以使用广度优先搜索的层次遍历去实现,大致模板如下

    if (root == null) {
        return;
    }
    Deque<TreeNode> queue = new LinkedList<>();
    queue.add(root);
    while (!queue.isEmpty()) {
        // 当前队列元素全部出队列,使用size保证是一个层级的出队列,即当前长度的元素同一层级的都出队列
        for (int i = 0, size = queue.size(); i < size; i++) {
            TreeNode node = queue.pop();
            // TODO 逻辑处理啥的
            // 将其左右节点继续放到队列中
            if (node.left != null) queue.add(node.left);
            if (node.right != null) queue.add(node.right);
        }
    }
    

    主要就是在于,将同一层的所有节点一起出队

  • 可适用于LeetCode102二叉树的层序遍历LeetCode103二叉树的锯齿形层序遍历LeetCode107二叉树的层序遍历 IILeetCode116填充每个节点的下一个右侧节点指针LeetCode117填充每个节点的下一个右侧节点指针 II LeetCode199二叉树的右视图LeetCode104二叉树的最大深度LeetCode111二叉树的最小深度

  • LeetCode102二叉树的层序遍历

    将每一层节点放到一个List中

    public List<List<Integer>> levelOrder(TreeNode root) {
            List<List<Integer>> ans = new ArrayList<>();
            if (root == null) {
                return ans;
            }
            Deque<TreeNode> queue = new LinkedList<>();
            queue.add(root);
            while (!queue.isEmpty()) {
                List<Integer> res = new ArrayList<>();
                // 当前队列元素全部出队列,使用size保证是一个层级的出队列,即当前长度的元素同一层级的都出队列
                for (int i = 0, size = queue.size(); i < size; i++) {
                    TreeNode node = queue.pop();
                    // 将其左右节点继续放到队列中
                    if (node.left != null) queue.add(node.left);
                    if (node.right != null) queue.add(node.right);
                    res.add(node.val);
                }
                ans.add(res);
            }
            return ans;
     }
    
  • LeetCode103二叉树的锯齿形层序遍历

    类似于102,只不过每层放到集合中,一次头插一次尾插,即一次从左至右一次从右至左

    public List<List<Integer>> zigzagLevelOrder(TreeNode root) {
        List<List<Integer>> ans = new LinkedList<>();
        if (root == null) return ans;
        Deque<TreeNode> queue = new LinkedList<>();
        queue.add(root);
        boolean left = true;
        while (!queue.isEmpty()) {
            LinkedList<Integer> res = new LinkedList<>();
            for (int i = 0, size = queue.size(); i < size; i++) {
                TreeNode node = queue.poll();
                if (node.left != null) queue.add(node.left);
                if (node.right != null) queue.add(node.right);
                // 入结果集调整顺序
                if (left) {
                    // 尾插
                    res.add(node.val);
                } else {
                    // 头插
                    res.addFirst(node.val);
                }
            }
            left = !left;
            ans.add(res);
        }
        return ans;
    }
    
  • LeetCode107二叉树的层序遍历 II

    还是类似于102,只不过入最后结果集的时候,采用的是头插法,即层次遍历从底至上

    public List<List<Integer>> levelOrderBottom(TreeNode root) {
            List<List<Integer>> ans = new LinkedList<>();
            if (root == null) {
                return ans;
            }
            Queue<TreeNode> queue = new LinkedList<>();
            queue.add(root);
            while (!queue.isEmpty()) {
    
                List<Integer> res = new LinkedList<>();
                for (int i = 0, size = queue.size(); i < size; i++) {
                    TreeNode node = queue.poll();
                    res.add(node.val);
                    if (node.left != null) queue.add(node.left);
                    if (node.right != null) queue.add(node.right);
                }
                ans.add(0, res);
            }
            return ans;
        }
    
  • LeetCode116填充每个节点的下一个右侧节点指针

    需要将每层节点之间建立next关系,可以考虑广度优先搜索实现,层次遍历给每层节点建立关系

    // 广度优先,层次遍历(一层一层出队)
        public Node connect(Node root) {
            if (root == null) return null;
            Deque<Node> queue = new LinkedList<>();
            queue.add(root);
            while (!queue.isEmpty()) {
                for (int i = 0, size = queue.size(); i < size; i++) {
                    Node node = queue.poll();
                    // 使用peek检索到队列头部值是什么,建立next关系
                    if (i < size - 1) {
                        node.next = queue.peek();
                    }
                    if (node.left != null) queue.add(node.left);
                    if (node.right != null) queue.add(node.right);
                }
            }
            return root;
        }
    
  • LeetCode117填充每个节点的下一个右侧节点指针 II

    从广度优先的角度来考虑这题跟106没有任何区别,这里只做广度优先层次遍历的讲解

    // 广度优先,层次遍历(一层一层出队)
        public Node connect(Node root) {
            if (root == null) return null;
            Deque<Node> queue = new LinkedList<>();
            queue.add(root);
            while (!queue.isEmpty()) {
                for (int i = 0, size = queue.size(); i < size; i++) {
                    Node node = queue.poll();
                    // 使用peek检索到队列头部值是什么,建立next关系
                    if (i < size - 1) {
                        node.next = queue.peek();
                    }
                    if (node.left != null) queue.add(node.left);
                    if (node.right != null) queue.add(node.right);
                }
            }
            return root;
        }
    
  • LeetCode199二叉树的右视图

    简单剖析下题目含义,即拼接二叉树每层最右边的节点,很明显的层次遍历思路

    public List<Integer> rightSideView(TreeNode root) {
            List<Integer> ans = new ArrayList<>();
            if (root == null) return ans;
            Deque<TreeNode> queue = new LinkedList<>();
            queue.add(root);
            while (!queue.isEmpty()) {
                for (int i = 0, size = queue.size(); i < size; i++) {
                    TreeNode node = queue.poll();
                    // 取最右边节点
                    if (i == size - 1) {
                        ans.add(node.val);
                    }
                    if (node.left != null) queue.add(node.left);
                    if (node.right != null) queue.add(node.right);
                }
            }
            return ans;
        }
    
  • LeetCode104二叉树的最大深度

    求最大深度,也即最大的层数

    public int maxDepthBFS(TreeNode root) {
            if (root == null) {
                return 0;
            }
            Deque<TreeNode> queue = new LinkedList<>();
            queue.add(root);
            int level = 0;
            while (!queue.isEmpty()) {
                for (int i = 0, size = queue.size(); i < size; i++) {
                    TreeNode node = queue.poll();
                    if (node.left != null) queue.add(node.left);
                    if (node.right != null) queue.add(node.right);
                }
                // 一层节点全部出完队列,层数+1
                level++;
            }
            return level;
        }
    
  • LeetCode111二叉树的最小深度

    求最小深度,即第一次出现叶子节点的那一层为最小深度

    public int minDepthBfs(TreeNode root) {
            if (root == null) return 0;
            Queue<TreeNode> queue = new LinkedList<>();
            queue.add(root);
            int ans = 1;
            while (!queue.isEmpty()) {
                for (int i = 0, size = queue.size(); i < size; i++) {
                    TreeNode node = queue.poll();
                    // 没有孩子节点了,即叶子节点,最小层数(深度)找到了
                    if (node.left == null && node.right == null) {
                        return ans;
                    }
                    if (node.left != null) queue.add(node.left);
                    if (node.right != null) queue.add(node.right);
                }
                ans++;
            }
            return ans;
        }
    
  • 以上题目可能不止一种解法,广度优先搜索层次遍历只是其中的一种方法、也是最容易想到的方法,但并不代表是最优解

  • 总结

    处理跟层数相关的题目、或处理每层节点的题目,可以考虑使用该方法层次遍历解决

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值