BFS是最简便的图的搜索算法之一,dijkstra单元最短路径算法和prime最小生成树算法都采用了和广度优先搜索类似的算法,
属于一种盲目算法,目的是系统地展开并检查图中所有节点,以寻找结果,和DFS的区别,dfs是一条路走到黑,如果没有路就返回,BFS是从上往下依次遍历,一般用队列来实现BFS
1.最短路径问题 通过bfs找到两个节点之间的最短路径
2.迷宫问题 可以用bfs来搜索迷宫中的最短路径,起点到终点
3.层级遍历 bfs可以按层级遍历树或图的节点,逐层处理
4.图的连通性 bfs可以用于确定两个节点之间是否存在路径或者图中的联通组件
5 单词变换问题
// 计算从起点 start 到终点 target 的最近距离
int BFS(Node start, Node target) {
Queue<Node> q; // 核心数据结构
Set<Node> visited; // 避免走回头路
q.offer(start); // 将起点加入队列
visited.add(start);
while (q not empty) {
int sz = q.size();
/* 将当前队列中的所有节点向四周扩散 */
for (int i = 0; i < sz; i++) {
Node cur = q.poll();
/* 划重点:这里判断是否到达终点 */
if (cur is target)
return step;
/* 将 cur 的相邻节点加入队列 */
for (Node x : cur.adj()) {
if (x not in visited) {
q.offer(x);
visited.add(x);
}
}
}
}
// 如果走到这里,说明在图中没有找到目标节点
}
思路 一眼就是bfs进行暴力搜索,将烂橘子的四周全部变成烂橘子,然后不断的网下,刚开始先搜索一下整张图,找出正常橘子的数目,将烂橘子添加到队列中去,当烂橘子感染周围橘子的时候,直接添加到队列中去。
import java.time.Year;
import java.util.Deque;
import java.util.LinkedList;
import java.util.Queue;
//leetcode submit region begin(Prohibit modification and deletion)
class Solution {
public int orangesRotting(int[][] grid) {
//分析,一眼bfs,广度优先搜索,找到一个烂的橘子,让他的四周都变成烂橘子
int m=grid.length;
int n=grid[0].length;
int count=0; //记录橘子的数量
Queue<int []> queue=new LinkedList<>(); //定义队列
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (grid[i][j]==2){
queue.offer(new int[]{i,j}); //将当前的坐标加进来
} else if (grid[i][j]==1) {
count++;
}
}
}
int time=0;
//先把图遍历一遍
if (count==0){
return 0;
}
while (!queue.isEmpty()){
if (count==0){
return time;
}
int size= queue.size();
for (int i = 0; i < size; i++) {
int [] orange=queue.poll(); //出队列
int x=orange[0];
int y=orange[1]; //烂橘子的坐标
if (x-1>=0&&grid[x-1][y]==1){
grid[x-1][y]=2;//变为烂橘子
count--;
queue.offer(new int[]{x-1, y});
}
if (x+1<m&&grid[x+1][y]==1){
grid[x+1][y]=2;//变为烂橘子
count--;
queue.offer(new int[]{x+1, y});
}
if (y-1>=0&&grid[x][y-1]==1){
grid[x][y-1]=2;//变为烂橘子
count--;
queue.offer(new int[]{x, y-1});
}
if (y+1<n&&grid[x][y+1]==1){
grid[x][y+1]=2;//变为烂橘子
count--;
queue.offer(new int[]{x, y+1});
}
}
time++; //每感染一次时间都会++;
}
return -1;
}
}
//leetcode submit region end(Prohibit modification and deletion)
可以用bfs求解,一层一层的去遍历,用队列去模拟,如果一共节点的左孩子和右孩子都为null,返回这一层所在的深度,就是二叉树的最小深度。
如果左右孩子不等于null,就将左右孩子都添加到队列中来。
class Solution {
int minDepth(TreeNode root) {
if (root==null){
return 0;
}
//dfs 广度优先搜索
Queue<TreeNode> queue =new LinkedList<>();
queue.offer(root); //将根节点添加进来
int depth=1; //原始的深度
//用队列来模拟功能
while (!queue.isEmpty()){
int size=queue.size();
for (int i = 0; i <size ; i++) {
TreeNode cur = queue.poll();
if (cur.left==null&&cur.right==null){
//左右都为null,说明了是根节点了
return depth;
}
if (cur.left!=null){
queue.offer(cur.left);
}
if (cur.right!=null){
queue.offer(cur.right);
}
}
depth++;
}
return depth;
}
}
蓝桥杯2019省赛迷宫问题
迷宫的入口在左上角,出口在左下角,在迷宫中只能从一个位置到另一个位置,DULR代表方向,向上,向下,向左,向右走;
可以
思路 定义一共静态的内部类,变量有x坐标,y坐标,走的步数,走的步在这里插入代码片
数对应的字符
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.LinkedList;
import java.util.Queue;
public class 迷宫2 {
static int num;
static int xsize = 30;
static int ysize = 50;
static char[][] arr = new char[xsize][ysize];
static boolean[][] help = new boolean[xsize][ysize];
static int[][] dir = {{1, 0}, {0, -1}, {0, 1}, {-1, 0}};
static char[] sign = {'D', 'L', 'R', 'U'};
// 定义节点类 Node
public static class Node {
int x; // 节点的 x 坐标
int y; // 节点的 y 坐标
String num; // 节点的值
int runnum; // 节点的运行值
// 构造函数,用于初始化节点对象
public Node(int x, int y, String num, int runnum) {
this.x = x;
this.y = y;
this.num = num;
this.runnum = runnum;
}
}
public static void main(String[] args) throws IOException {
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
// 读取迷宫数据到二维数组 arr
for (int i = 0; i < xsize; i++) {
arr[i] = in.readLine().toCharArray();
}
// 调用 bfs() 方法执行广度优先搜索
out.println(bfs());
out.print(num);
out.flush();
}
// 广度优先搜索方法
static String bfs() {
Queue<Node> list = new LinkedList<>();
int x = 0;
int y = 0;
int runnum = 0;
list.add(new Node(x, y, "", runnum));
while (!list.isEmpty()) {
Node now = list.poll();
help[now.x][now.y] = true;
// 遍历四个方向进行移动
for (int i = 0; i < 4; i++) {
int xx = now.x + dir[i][0];
int yy = now.y + dir[i][1];
// 检查下一个位置是否合法
if (check(xx, yy) && !help[xx][yy] && arr[xx][yy] == '0') {
list.add(new Node(xx, yy, now.num + sign[i], now.runnum + 1));
// 判断是否到达终点
if (xx == xsize - 1 && yy == ysize - 1) {
num = now.runnum + 1;
return now.num + sign[i];
}
}
}
}
return "";
}
// 辅助方法,检查坐标是否在合法范围内
private static boolean check(int xx, int yy) {
return xx >= 0 && yy >= 0 && xx < xsize && yy < ysize;
}
}