Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >BFS(Breath First Search 广度优先搜索)

BFS(Breath First Search 广度优先搜索)

原创
作者头像
刘大猫
发布于 2024-11-01 07:30:06
发布于 2024-11-01 07:30:06
870
举报
文章被收录于专栏:算法题算法题

@TOC

一、知识及框架

  1. BFS算法都是用 “队列” 结构undefined ※ 思考问题1:为什么bfs、dfs都可以找到最短距离,但一般都使用bfs方法,而不用dfs呢? 答:bfs是齐头并进,一旦找到终点就不找了,而dfs需要全遍历后才知道最短路径
  2. BFS和DFS最主要区别:bfs找到的路径一定是最短的,但代价是空间复杂度比dfs大很多
  3. bfs本质:一幅图,从起点到终点,求最短路径
  4. bfs空间复杂度高,而dfs空间复杂度较低
  5. 形象点说:dfs是线,bfs是面,dfs是单打独斗,bfs是集体行动
  6. dfs和bfs的时间复杂度都是O(N)
  7. BFS干的事:从起点start到终点target的最近距离
  8. BFS应用举例:走迷宫、连连看......

※ 思考问题2:既然bfs那么好,为啥dfs还需要存在?

答:bfs代价太大,除找最短路径用bfs,其他情况推荐dfs

==BFS框架:==

二、案例说明

==说明==:Node节点class对象代码请查看上一篇文章,https://blog.csdn.net/a924382407/article/details/118394577

二叉树

代码语言:java
AI代码解释
复制
		/*   a1:↓                           a2:↓                  a3:↓
                1                               1                     1
               / \                                                   / \
              2   3                                                 2   3
             / \
            4   5
               /
              6
         */
        Node a1 = new Node(1, new Node(2, new Node(4), new Node(5, new Node(6), null)), new Node(3));
        Node a2 = new Node(1, null, null);
        Node a3 = new Node(1, new Node(2, null, null), new Node(3, null, null));

main函数

代码语言:java
AI代码解释
复制
public static void main(String[] args){
		//问题3.1:使用bfs计算二叉树的最小高度
        System.out.println("使用bfs计算二叉树的最小高度:" + bfsMinDepth(a1));
        //问题3.2:解开密码锁的最少次数
        System.out.println("解开密码锁的最少次数:" + openLock(new String[]{"8887", "7789"}, "8888"));
}

案例1:使用bfs计算二叉树的最小高度

代码语言:java
AI代码解释
复制
	//问题3.1:使用bfs计算二叉树的最小高度
    public static int bfsMinDepth(Node root) {
        if (root == null) return 0;
        Queue<Node> q = new LinkedList<>();
        q.offer(root);
        //root本身就是一层,将depth初始化为1
        int depth = 1;

        while (!q.isEmpty()) {
            int sz = q.size();
            //将当前队列中所有节点想四周扩散
            for (int i = 0; i < sz; i++) {
                Node cur = q.poll();
                //判断是否到达终点
                if (cur.left == null && cur.right == null) return depth;
                //将cur的相邻节点加入队列
                if (cur.left != null) q.offer(cur.left);
                if (cur.right != null) q.offer(cur.right);
            }
            //重点:这里增加步数
            depth++;
        }
        return depth;
    }

案例2:解开密码锁的最少次数,要求:请写一个算法,初始状态为0000,拨出target的最少次数,其中避免出现deadends中的包含的任意一个死亡密码,如果永远无法拨出target,则返回-1

代码语言:java
AI代码解释
复制
	/**
     * 问题3.2:解开密码锁的最少次数
     *      要求:请写一个算法,初始状态为0000,拨出target的最少次数,其中避免出现deadends中的包含的任意一个死亡密码,如果永远无法拨出target,则返回-1
     */
    //将s[j]向上拨动一次
    public static String plusOne(String s, int j) {
        char[] ch = s.toCharArray();
        if (ch[j] == '9') {
            ch[j] = '0';
        } else {
            ch[j] += 1;
        }
        return new String(ch);
    }
    
    //将s[j]向下拨动一次
    public static String minusOne(String s, int j) {
        char[] ch = s.toCharArray();
        if (ch[j] == '0') {
            ch[j] = '9';
        } else {
            ch[j] -= 1;
        }
        return new String(ch);
    }
    
    /**
     * openLock
     * @param deadends 死亡数字
     * @param target  目标密码
     * @return 次数
     */
    public static int openLock(String[] deadends, String target) {
        //记录需要跳过的死亡密码
        Set<String> deads = new HashSet<>();
        for (String s : deadends) deads.add(s);
        //记录已经穷举过的密码,防止走回头路
        Set<String> visited = new HashSet<>();
        Queue<String> q = new LinkedList<>();
        //从起点开始启动广度搜先搜索
        int step = 0;
        q.offer("0000");
        visited.add("0000");

        while (!q.isEmpty()) {
            int sz = q.size();
            //将当前队列中所有节点向四周扩散
            for (int i = 0; i < sz; i++) {
                String cur = q.poll();
                //判断密码是否合法,是否到达终点
                if (deads.contains(cur)) continue;
                if (cur.equals(target)) return step;
                //将一个节点的未遍历相邻节点加入队列
                for (int j = 0; j < 4; j++) {
                    String up = plusOne(cur, j);
                    if (!visited.contains(up)) {
                        q.offer(up);
                        visited.add(up);
                    }
                    String down = minusOne(cur, j);
                    if (!visited.contains(down)) {
                        q.offer(down);
                        visited.add(down);
                    }
                }
            }
            //重点:增加步数
            step++;
        }
        //如果穷举完都没找到目标密码,那就是找不到了
        return -1;
    }

本人其他文章链接

1.单链表题+数组题(快慢指针和左右指针)

2.BFS(Breath First Search 广度优先搜索)

3.”回溯算法“框架及练习题

4.JAVA 二叉树面试题

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
【C++】算法集锦(5):BFS算法
BFS算法和DFS算法属于图论算法的范畴,DFS在前面回溯中,可以去看一下。 BFS算法用于寻找两点之间的最短路径。
看、未来
2021/09/18
6710
BFS 算法框架套路详解
首先,你要说 labuladong 没写过 BFS 框架,这话没错,今天写个框架你背住就完事儿了。但要是说没写过 DFS 框架,那你还真是说错了,其实 DFS 算法就是回溯算法,我们前文 回溯算法框架套路详解 就写过了,而且写得不是一般得好,建议好好复习。
labuladong
2021/09/23
7440
【python刷题】广度优先搜索(BFS)
一般来说,BFS使用的数据结构是队列。 BFS模板 from collections import deque def BFS(start, target): q = deque() # 核心数据结构 visited = set() # 避免走回头路 q.append(start) # 将起点加入到队列 visited.add(start) step = 0 # 记录扩散的步数 while q is not None: s = len(q)
西西嘛呦
2021/02/05
1.1K0
算法学习记录
一、介绍 1、常见的数据结构 「队列」、「栈」这两种数据结构既可以使⽤链表也可以使⽤数组实现。⽤数组实现,就要处理扩容缩容的问题;⽤链表实现,没有这个问题,但需要更多的内存空间存储节点指针。 「图」的两种表⽰⽅法,邻接表就是链表,邻接矩阵就是⼆维数组。邻接矩阵判断连通性迅速,并可以进⾏矩阵运算解决⼀些问题,但是如果图⽐较稀疏的话很耗费空间。邻接表⽐较节省空间,但是很多操作的效率上肯定⽐不过邻接矩阵。 「散列表」就是通过散列函数把键映射到⼀个⼤数组⾥。⽽且对于解决散列冲突的⽅法,拉链法需要链表特性,操作
MiChong
2020/11/17
4600
BFS算法总结
要解决的问题,大体是在一副“图”中,找到从起点start 到 终点target 的最近距离。
艳龙
2021/12/16
3020
我写了一个模板,把 Dijkstra 算法变成了默写题
其实,很多算法的底层原理异常简单,无非就是一步一步延伸,变得看起来好像特别复杂,特别牛逼。
labuladong
2021/09/23
1.6K0
leetcode刷题(110)——752. 打开转盘锁
你有一个带有四个圆形拨轮的转盘锁。每个拨轮都有10个数字: ‘0’, ‘1’, ‘2’, ‘3’, ‘4’, ‘5’, ‘6’, ‘7’, ‘8’, ‘9’ 。每个拨轮可以自由旋转:例如把 ‘9’ 变为 ‘0’,‘0’ 变为 ‘9’ 。每次旋转都只能旋转一个拨轮的一位数字。
老马的编程之旅
2022/06/22
2560
初识广度优先搜索与解题套路
先来看看其中比较简单的数据结构 - 链表,它和数组类似,也是一个线性的结构,简单来说就是一条路径,你从头开始遍历,最终会将链表上面的节点都访问到,到达终点。
五分钟学算法
2019/10/09
6070
二、进阶数据结构
二叉树题目的递归解法可以分两类思路,第一类是遍历一遍二叉树得出答案,第二类是通过分解问题计算出答案,这两类思路分别对应着 回溯算法核心框架 和 动态规划核心框架。
阿东知识库
2024/09/03
1840
二、进阶数据结构
Python 算法基础篇:深度优先搜索( DFS )和广度优先搜索( BFS )
深度优先搜索( DFS )和广度优先搜索( BFS )是两种常用的图遍历算法,用于在图中搜索目标节点或遍历图的所有节点。本篇博客将介绍 DFS 和 BFS 算法的基本概念,并通过实例代码演示它们的应用。
小蓝枣
2023/07/22
3.1K0
搞定大厂算法面试之leetcode精讲21.树
树这种数据结构包括根节点root,左右节点,子树中又有父节点,子节点,兄弟节点,没有子节点的成为叶子节点,树分为二叉树和多叉树
全栈潇晨
2021/12/06
5680
队列+宽搜
给你二叉树的根节点 root ,返回其节点值的 锯齿形层序遍历 。(即先从左往右,再从右往左进行下一层遍历,以此类推,层与层之间交替进行)。
用户11369558
2024/12/24
1250
队列+宽搜
​LeetCode刷题实战102:二叉树的层序遍历
算法的重要性,我就不多说了吧,想去大厂,就必须要经过基础知识和业务逻辑面试+算法面试。所以,为了提高大家的算法能力,这个公众号后续每天带大家做一道算法题,题目就从LeetCode上面选 !
程序员小猿
2021/01/20
2990
​LeetCode刷题实战102:二叉树的层序遍历
我的刷题经验总结
两年前刚开这个公众号的时候,我写了一篇 学习数据结构和算法的框架思维,现在已经 5w 多阅读了,这对于一篇纯技术文来说是很牛逼的数据。
labuladong
2021/10/14
8030
java算法刷题02——深度优先搜索与广度优先搜索
给一个01矩阵,1代表是陆地,0代表海洋, 如果两个1相邻,那么这两个1属于同一个岛。我们只考虑上下左右为相邻。 岛屿: 相邻陆地可以组成一个岛屿(相邻:上下左右) 判断岛屿个数。 例如: 输入 [ [1,1,0,0,0], [0,1,0,1,1], [0,0,0,1,1], [0,0,0,0,0], [0,0,1,1,1] ] 对应的输出为3 示例1 输入:
半旧518
2022/10/26
6660
java算法刷题02——深度优先搜索与广度优先搜索
算法:树
在之前的内容中我们学习了链表的这一基础数据结构,单链表是其中的一种,结构形式如下所示:
用户3578099
2022/03/15
7530
算法:树
数据结构与算法——BFS(广度优先搜索)
广度优先搜索(Breadth-First Search,简称BFS)是一种遍历或搜索树和图的算法,也称为宽度优先搜索,BFS算法从图的某个节点开始,依次对其所有相邻节点进行探索和遍历,然后再对这些相邻节点的相邻节点进行探索,直到遍历完所有的节点。BFS算法使用队列来辅助实现,将起始节点放入队列中,然后依次取出队列中的节点,访问其相邻节点,并将其加入队列。这样可以保证从起始节点出发,依次按照距离顺序遍历节点。BFS常用于寻找最短路径,因为它按照从起点到每个节点的距离来探索节点。
摆烂小白敲代码
2024/09/23
3380
数据结构与算法——BFS(广度优先搜索)
开发成长之路(16)-- 算法小抄:思维跃迁
复杂度分析: 在一般情况下,每一个数都要与之后的数进行匹配,所以匹配次数将与数据量n挂钩,又由于每轮匹配都要进行(n-1)次比较,所以平均时间复杂度为O(n^2)。
看、未来
2021/09/18
3580
几道和「广度优先搜索」有关的算法面试题
2、从 V0 出发,访问 V0 的各个 未被访问 的邻接点 W1, W2,…, Wk ;然后依次从 W1, W2,…, Wk 出发访问各自未被访问的邻接点;
五分钟学算法
2019/05/06
6980
几道和「广度优先搜索」有关的算法面试题
几乎刷完了力扣所有的树题,我发现了这些东西。。。
先上下本文的提纲,这个是我用 mindmap 画的一个脑图,之后我会继续完善,将其他专题逐步完善起来。
Nealyang
2020/12/03
3.3K0
几乎刷完了力扣所有的树题,我发现了这些东西。。。
相关推荐
【C++】算法集锦(5):BFS算法
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档