广度优先搜索

Posted 浮云神码

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了广度优先搜索相关的知识,希望对你有一定的参考价值。

    本次接着分享广度优先搜索,其中 【填充每个节点的下一个右侧节点指针】除了提供广度优先搜索的解法一外,还提供了进阶版解法二。


import java.util.LinkedList;import java.util.Queue;
/** * https://leetcode-cn.com/problems/minimum-depth-of-binary-tree * 111. 二叉树的最小深度 * 难度 简单 * 给定一个二叉树,找出其最小深度。 * * 最小深度是从根节点到最近叶子节点的最短路径上的节点数量。 * * 说明:叶子节点是指没有子节点的节点。 * * 示例 1: * * * 输入:root = [3,9,20,null,null,15,7] * 输出:2 * 示例 2: * * 输入:root = [2,null,3,null,4,null,5,null,6] * 输出:5 * * 提示: * * 树中节点数的范围在 [0, 105] 内 * -1000 <= Node.val <= 1000 * * 来源:力扣(LeetCode) * 链接:https://leetcode-cn.com/problems/minimum-depth-of-binary-tree */public class MinDepthTree {
public int minDepth(TreeNode root) { int depth = 0; if (root == null) { return depth; } /** * 使用广度优先搜索算法, 借助队列来实现 */ Queue<TreeNode> queue = new LinkedList<>(); queue.add(root); depth += 1;
while (!queue.isEmpty()) { int size = queue.size(); // 遍历当前层级的节点 for (int i = 0; i < size; i++) { TreeNode current = queue.remove(); // 左右节点都为空, 说明已到达叶子节点, 直接返回当前depth, 即为树的最小高度 if (current.left == null && current.right == null) { return depth; } // 将左右子节点加入队列, 在下次while迭代时使用 if (current.left != null) { queue.add(current.left); }
if (current.right != null) { queue.add(current.right); } }
depth += 1; } return depth; }}


import java.util.LinkedList;import java.util.Queue;
/** * https://leetcode-cn.com/problems/populating-next-right-pointers-in-each-node * 116. 填充每个节点的下一个右侧节点指针 * 难度 中等 * 给定一个完美二叉树,其所有叶子节点都在同一层,每个父节点都有两个子节点。二叉树定义如下: * * struct Node { * int val; * Node *left; * Node *right; * Node *next; * } * 填充它的每个 next 指针,让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点,则将 next 指针设置为 NULL。 * * 初始状态下,所有next 指针都被设置为 NULL。 * * 进阶: * * 你只能使用常量级额外空间。 * 使用递归解题也符合要求,本题中递归程序占用的栈空间不算做额外的空间复杂度。 * * 示例: * 输入:root = [1,2,3,4,5,6,7] * 输出:[1,#,2,3,#,4,5,6,7,#] * 解释:给定二叉树如图 A 所示,你的函数应该填充它的每个 next 指针,以指向其下一个右侧节点,如图 B 所示。序列化的输出按层序遍历排列,同一层节点由 next 指针连接,'#' 标志着每一层的结束。 * * 提示: * * 树中节点的数量少于4096 * -1000 <= node.val <= 1000 * * 来源:力扣(LeetCode) * 链接:https://leetcode-cn.com/problems/populating-next-right-pointers-in-each-node */public class PopulatingNextTree {
/** * 解法一: 广度优先搜索 * @param root * @return */ public Node connect(Node root) { if (root == null) { return null; } // 借助队列实现 Queue<Node> queue = new LinkedList<>(); queue.add(root);
while (!queue.isEmpty()) { int size = queue.size(); // 每个层级, 首先将prev置为null Node prev = null;
for (int i = 0; i < size; i++) { Node current = queue.remove(); // 设置过prev之后, 即for循环执行过一次之后, 才会开始设置next if (prev != null) { prev.next = current; } // prev不断向右移动 prev = current; // 完美二叉树, 只需要判断一个子节点就可以 if (current.left != null) { queue.add(current.left); queue.add(current.right); } } } return root; }
/** * 解法二:进阶, 常量级额外空间 * @param root * @return */ public Node connect2(Node root) { /** * 主要思想是使用两个指针, 1 current:指向当前处理的层级; 2 childHead: 指向每层最左边的子节点 * 当前层级使用next指针进行遍历, 用来连接下一层节点的next指针(注意:当前节点已被上层节点连接起来了, 而root节点不需要连接) */ Node current = null; Node childHead = root; while (childHead != null) { // 重置当前层级, 指向childHead, 而childHead指向左子节点 current = childHead; childHead = childHead.left;
while (current != null) { // 注意是满二叉树, 只判断一个子节点就可以了, right 和 next.left都不需要再次判断 if (current.left != null) { // 左右子节点相连 current.left.next = current.right;
// 如果存在next节点, 则将右子节点和next的左子节点相连 if (current.next != null) { current.right.next = current.next.left; } } // 当前节点指针后移 current = current.next; } }
return root; }}


以上是关于广度优先搜索的主要内容,如果未能解决你的问题,请参考以下文章

Prolog中的广度优先搜索

面试题算法: 广度优先搜索

图相关算法

图解:深度优先搜索与广度优先搜索

广度优先搜索遍历图

无向图 广度优先搜索 和 深度优先搜索