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

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

image.png

@[TOC]

一、知识及框架

  1. BFS算法都是用 “队列” 结构
  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应用举例:走迷宫、连连看......

※ 思考问题1:为什么bfs、dfs都可以找到最短距离,但一般都使用bfs方法,而不用dfs呢?
答:bfs是齐头并进,一旦找到终点就不找了,而dfs需要全遍历后才知道最短路径

※ 思考问题2:既然bfs那么好,为啥dfs还需要存在?
答:bfs代价太大,除找最短路径用bfs,其他情况推荐dfs

==BFS框架:==
image.png

二、案例说明

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

二叉树

        /*   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函数

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计算二叉树的最小高度

    //问题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

    /**
     * 问题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 二叉树面试题

目录
相关文章
|
IDE 关系型数据库 开发工具
使用Visual Basic进行Windows窗体开发
【4月更文挑战第27天】本文介绍了使用Visual Basic进行Windows窗体(WinForms)开发的步骤,从搭建开发环境到创建、设计用户界面,再到编写事件驱动的代码和数据绑定。Visual Basic结合WinForms提供了一种易学易用的桌面应用开发方案。通过调试、优化、部署和维护,开发者可以构建专业应用程序。随着技术发展,掌握最新UI设计和开发工具对于保持竞争力至关重要。本文为初学者提供了基础指导,鼓励进一步探索和学习。
424 0
|
机器学习/深度学习 传感器 数据可视化
基于matlab模拟无线网络拓扑、估计链路质量并可视化拓扑
基于matlab模拟无线网络拓扑、估计链路质量并可视化拓扑
|
10月前
|
数据采集 监控 前端开发
提升当当网数据爬取效率:代理IP并发抓取技术
提升当当网数据爬取效率:代理IP并发抓取技术
|
9月前
|
存储 NoSQL 关系型数据库
从大数据到大模型:如何做到“心无桎梏,身无藩篱”
在大数据和大模型的加持下,现代数据技术释放了巨大的技术红利,通过多种数据范式解除了数据的桎梏,使得应用程序达到了“心无桎梏,身无藩篱”的自在境界,那么现代应用有哪些数据范式呢?这正是本文尝试回答的问题。
1503 101
|
8月前
|
存储 开发工具 git
[Git] 深入理解 Git 的客户端与服务器角色
Git 的核心设计理念是分布式,每个仓库既可以是客户端也可以是服务器。通过 GitHub 远程仓库和本地仓库的协作,Git 实现了高效的版本管理和代码协作。GitHub 作为远程裸仓库,存储项目的完整版本历史并支持多客户端协作;本地仓库则通过 `.git` 文件夹独立管理版本历史,可在离线状态下进行提交、回滚等操作,并通过 `git pull` 和 `git push` 与远程仓库同步。这种分布式特性使得 Git 在代码协作中具备强大的灵活性和可靠性。
199 18
[Git] 深入理解 Git 的客户端与服务器角色
|
6月前
|
固态存储 C++ 计算机视觉
Windows平台GIMP 2.10下载教程:零基础入门高级图像编辑
GIMP(GNU Image Manipulation Program)是一款开源跨平台图像编辑工具,支持图层管理、高级修图、色彩校正等功能,广泛应用于平面设计和照片修复。其优势包括全功能免费、插件生态丰富(600+扩展插件)、硬件要求低(1GB内存即可流畅运行)。本文详细介绍GIMP的软件定位、安装流程、首次配置及常见问题解答,帮助用户快速上手并充分利用其强大功能。
|
10月前
|
敏捷开发 数据可视化 BI
工作流管理是什么?5款企业工作流管理工具推荐!
工作流管理是一种使处理过程自动化、协调人和应用工具完成工作的技术。它通过规划、组织、协调和控制业务流程,确保工作高效、准确地完成。工作流管理可以提高工作效率、规范业务流程、增强协同工作能力、优化决策支持,并提升企业竞争力。本文介绍了5款工作流管理软件:板栗看板、Trello、Asana、Jira 和 Monday.com,它们各具特色,适用于不同的场景和需求。
工作流管理是什么?5款企业工作流管理工具推荐!
|
10月前
|
算法 Python
Python 大神修炼手册:图的深度优先&广度优先遍历,深入骨髓的解析
在 Python 编程中,掌握图的深度优先遍历(DFS)和广度优先遍历(BFS)是进阶的关键。这两种算法不仅理论重要,还能解决实际问题。本文介绍了图的基本概念、邻接表表示方法,并给出了 DFS 和 BFS 的 Python 实现代码示例,帮助读者深入理解并应用这些算法。
262 2
|
监控 网络协议 算法
在Linux中,如何进行网络性能调优?
在Linux中,如何进行网络性能调优?
|
存储 算法 Java
广度优先搜索(Breadth-First Search,BFS)是一种用于图的遍历或搜索的算法。
广度优先搜索(Breadth-First Search,BFS)是一种用于图的遍历或搜索的算法。

热门文章

最新文章