广度优先搜索
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;
}
}
以上是关于广度优先搜索的主要内容,如果未能解决你的问题,请参考以下文章