BFS 算法专题(三):BFS 解决边权为 1 的最短路问题

目录

1. 迷宫中离入口最近的出口 

1.1 算法原理

1.2 算法代码

2. 最小基因变化 ★★★

2.1 算法原理

2.2 算法代码

3. 单词接龙

3.1 算法原理

3.2 算法代码

4. 为高尔夫比赛砍树 (hard)

4.1 算法原理

 4.2 算法代码


1. 迷宫中离入口最近的出口 

. - 力扣(LeetCode)

1.1 算法原理

核心问题: 图论 => 边权为1/边权相同 的最短路径问题

解法: 从起点开始, 进行 BFS 扩展, 第一次到达终点时, 扩展的层数, 就是最短的路径.

如何记录 BFS 扩展的层数呢??
--- 借助每一层中节点的数量(queue.size()), 使用变量 ret 记录扩展的层数.

1.2 算法代码

class Solution {
    public int nearestExit(char[][] maze, int[] entrance) {
        int[] dx = { 1, -1, 0, 0 };
        int[] dy = { 0, 0, 1, -1 };
        // 记录到达终点时, BFS 的层数
        int ret = 0;
        int m = maze.length, n = maze[0].length;
        boolean[][] check = new boolean[m][n];
        Queue<int[]> q = new LinkedList<>();
        q.offer(entrance);
        check[entrance[0]][entrance[1]] = true;
        while (!q.isEmpty()) {
            int size = q.size();
            ret++;
            while (size-- != 0) {
                int[] tmp = q.poll();
                int a = tmp[0], b = tmp[1];
                for (int k = 0; k < 4; k++) {
                    int x = a + dx[k], y = b + dy[k];
                    if (x >= 0 && x < m && y >= 0 && y < n && !check[x][y] && maze[x][y] == '.') {
                        if (x == 0 || x == m - 1 || y == 0 || y == n - 1) return ret;
                        q.offer(new int[] { x, y });
                        check[x][y] = true;
                    }
                }
            }
        }
        return -1;
    }
}

2. 最小基因变化 ★★★

. - 力扣(LeetCode)

2.1 算法原理

问题转化: 转化为 => 图论 边权为1的最短路问题

  1. 每变一个字符(基因的变化)看做一步, BFS 选出达到目标基因序列时的最短路.
  2. 注意: 不能重复搜索已经搜索过的状态
  3. 注意: 经过变化的字符串, 应该在 bank 基因库中存在
  4. 使用 哈希表 标记已经搜索过的状态
  5. 使用 哈希表 保存基因库中的字符(便于查找变化的字符串是否在基因库中)

2.2 算法代码

class Solution {
    public int minMutation(String startGene, String endGene, String[] bank) {
        Queue<String> q = new LinkedList<>();
        // 判断是否重复转化
        Set<String> check = new HashSet<>();
        // 判断基因库中是否存在
        Set<String> hash = new HashSet<>();
        for(String s : bank) hash.add(s);
        
        if(!hash.contains(endGene)) return -1;
        if(startGene.equals(endGene)) return 0;

        char[] change = {'A', 'C', 'G', 'T'};

        int ret = 0;
        q.offer(startGene);
        check.add(startGene);
        while(!q.isEmpty()) {
            int size = q.size();
            ret++;
            while(size-- != 0) {
                String s = q.poll();
                for(int i = 0; i < 8; i++) {
                    char[] tmp = s.toCharArray();
                    for(int j = 0; j < 4; j++) {
                        tmp[i] = change[j];
                        String next = new String(tmp);
                        if(hash.contains(next) && !check.contains(next)) {
                            if(next.equals(endGene)) return ret;
                            check.add(next);
                            q.offer(next);
                        }
                    }
                }
            }
        }
        return -1;
    }
}

3. 单词接龙

. - 力扣(LeetCode)

3.1 算法原理

  • 本题解法与上题解法完全一致.

  • 只不过返回值略有差异. 本题返回达到目标字符串时, 所涉及到的最少的字符串的个数(最短路 +1)

3.2 算法代码

class Solution {
    public int ladderLength(String beginWord, String endWord, List<String> wordList) {
        // 把字典中的字符串, 放到哈希表中 => 查找效率 O(1)
        Set<String> hash = new HashSet<>(wordList);
        if(!hash.contains(endWord)) return 0;
        int n = beginWord.length();
        // 判断是否重复转化
        Set<String> check = new HashSet<>();
        Queue<String> q = new LinkedList<>();
        int step = 0;
        q.offer(beginWord);
        check.add(beginWord);
        while(!q.isEmpty()) {
            int size = q.size();
            step++;
            while(size-- != 0) {
                String s = q.poll();
                for(int i = 0; i < n; i++) {
                    char[] tmp = s.toCharArray();
                    for(char ch = 'a'; ch <= 'z'; ch++) {
                        tmp[i] = ch;
                        String next = new String(tmp);
                        if(hash.contains(next) && !check.contains(next)) {
                            if(next.equals(endWord)) return step + 1;
                            q.offer(next);
                            check.add(next);
                        }
                    }
                }
            }
        }
        return 0;
    }
}

4. 为高尔夫比赛砍树 (hard)

. - 力扣(LeetCode)

4.1 算法原理

  • 对砍树的顺序做好记录(所砍树的高度应从小到大), 并记录好每一颗树的位置.

  • 从起点开始, 对这些位置依次进行 BFS, 找出到达这些位置的最短路.

  • 返回到达所有位置所需最少步数之和

 4.2 算法代码

class Solution {
    int m, n;
    int[] dx = new int[] { 1, -1, 0, 0 };
    int[] dy = new int[] { 0, 0, 1, -1 };

    public int cutOffTree(List<List<Integer>> forest) {
        m = forest.size(); n = forest.get(0).size();
        List<int[]> trees = new ArrayList<>();
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (forest.get(i).get(j) > 1) trees.add(new int[] {i, j});
            }
        }
        // 依次需要砍的树(树的高度从小到大)
        Collections.sort(trees, (a, b) -> forest.get(a[0]).get(a[1]) - forest.get(b[0]).get(b[1]));
        int step = 0;
        int curX = 0, curY = 0;
        for (int[] t : trees) {
            int x = t[0], y = t[1];
            int ret = bfs(x, y, curX, curY, forest);
            if (ret == -1) return -1;
            step += ret;
            curX = x;
            curY = y;
        }
        return step;
    }

    public int bfs(int x, int y, int curX, int curY, List<List<Integer>> forest) {
        int ret = 0;
        if (curX == x && curY == y) return 0;
        boolean[][] check = new boolean[m][n];
        Queue<int[]> q = new LinkedList<>();
        q.offer(new int[] { curX, curY });
        check[curX][curY] = true;
        while (!q.isEmpty()) {
            int size = q.size();
            ret++;
            while (size-- != 0) {
                int[] t = q.poll();
                int a = t[0], b = t[1];
                for (int k = 0; k < 4; k++) {
                    int i = a + dx[k], j = b + dy[k];
                    if (i >= 0 && i < m && j >= 0 && j < n && forest.get(i).get(j) != 0 && !check[i][j]) {
                        if (forest.get(i).get(j) == forest.get(x).get(y))
                            return ret;
                        q.offer(new int[] { i, j });
                        check[i][j] = true;
                    }
                }
            }
        }
        return -1;
    }
}

END

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/915213.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Flink_DataStreamAPI_执行环境

DataStreamAPI_执行环境 1创建执行环境1.1getExecutionEnvironment1.2createLocalEnvironment1.3createRemoteEnvironment 2执行模式&#xff08;Execution Mode&#xff09;3触发程序执行 Flink程序可以在各种上下文环境中运行&#xff1a;我们可以在本地JVM中执行程序&#x…

46.第二阶段x86游戏实战2-拆解自动打怪流程

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 本次游戏没法给 内容参考于&#xff1a;微尘网络安全 本人写的内容纯属胡编乱造&#xff0c;全都是合成造假&#xff0c;仅仅只是为了娱乐&#xff0c;请不要…

解决C盘空间不足的三种方案

方案一&#xff1a;网上盛传的C盘磁盘碎片整理&#x1f9e9;&#xff08;原理&#xff1a;将分散的文件片段整理到相邻的磁盘区域&#xff0c;减少文件的碎片化程度&#xff09;(效果不明显) 方案二&#xff1a;把其他盘的空间给C盘 &#x1f4bd;&#xff08;效果显著&#xf…

同一套SDK 兼容第二块板卡

尽可能分开写,避免兼容性变差

计算机网络高频八股文面试题及参考答案

请简述 TCP 和 UDP 的区别&#xff1f; TCP&#xff08;传输控制协议&#xff09;和 UDP&#xff08;用户数据报协议&#xff09;是两种不同的传输层协议&#xff0c;它们有以下区别。 从连接方式上看&#xff0c;TCP 是面向连接的协议。在通信之前&#xff0c;需要通过三次握手…

前缀和算法习题篇(上)

1.一维前缀和 题目描述&#xff1a; 解法一&#xff1a;暴力解法&#xff1a;模拟 时间复杂度是O(n*q),会超时。 解法二&#xff1a;前缀和解法&#xff1a;快速求出数组中某一个连续区间的和 快速是指O(1),前缀和思想可把时间复杂度可降到O(q)。 算法思路&#xff1a; 先预处…

uniapp路由与页面跳转详解:API调用与Navigator组件实战

UniApp路由与页面跳转详解&#xff1a;API调用与Navigator组件实战 路由 uniapp页面路由为框架统一管理&#xff0c;开发者需要在page.json里面配置每个路由页面的路径及页面样式。 路由跳转 uniapp有两种页面路由跳转方式&#xff0c;调用API跳转和navigator组件跳转。 调…

linux-DNS解析

dns解析 dns&#xff1a;域名系统&#xff0c;将域名和ip地址互相映射的一个分布式的数据库&#xff0c;方便用户访问互联网。 ip地址&#xff1a;是所有设备和网站在互联网上的唯一地址&#xff0c;通信一定是ip和ip之间的通信。 dns解析&#xff1a;根据域名在互联网当中找…

Playwright 快速入门:Playwright 是一个用于浏览器自动化测试的 Node.js 库

Playwright 是一个用于浏览器自动化测试的 Node.js 库&#xff0c;它支持 Chromium, Firefox 和 WebKit 浏览器引擎。Playwright 提供了一套强大的 API 来进行网页自动化测试&#xff0c;包括页面导航、元素选择、表单提交等操作&#xff0c;并且能够处理现代网页中的异步加载内…

【maven踩坑】一个坑 junit报错 但真正导致这个的不是junit的原因

目录 事件起因环境和工具操作过程解决办法结束语 事件起因 报错一&#xff1a; Internal Error occurred. org.junit.platform.commons.JUnitException: TestEngine with ID junit-vintage failed to discover tests报错二&#xff1a; Internal Error occurred. org.junit.pl…

ONNX: export failure: DLL load failed while importing _message: 找不到指定的程序。

ONNX: export failure 问题其他解决快速解决 问题 使用pytorch导出onnx&#xff08;Open Neural Network Exchange&#xff09;模型&#xff0c;结果使用conda安装完onnx之后&#xff0c;问题就出现了 ONNX: export failure: DLL load failed while importing _message: 找不到…

Redis做分布式锁

&#xff08;一&#xff09;为什么要有分布式锁以及本质 在一个分布式的系统中&#xff0c;会涉及到多个客户端访问同一个公共资源的问题&#xff0c;这时候我们就需要通过锁来做互斥控制&#xff0c;来避免类似于线程安全的问题 因为我们学过的sychronized只能对线程加锁&…

用Tokio掌握Rust异步编程

在Rust中构建可伸缩且高效的应用程序时&#xff0c;异步编程必不可少。异步编程能显著提高性能&#xff0c;让代码在不阻塞的情况下并发处理多个任务。在本教程中&#xff0c;我们将探索Tokio&#xff0c;介绍异步编程原理及应用场景&#xff0c;并逐步带你编写异步代码。 Toki…

推荐一款3D建模软件:Agisoft Metashape Pro

Agisoft Metashape Pro是一款强大的多视点三维建模设计辅助软件&#xff0c;Agisoft Metashape是一款独立的软件产品&#xff0c;可对数字图像进行摄影测量处理&#xff0c;并生成3D空间数据&#xff0c;用于GIS应用&#xff0c;文化遗产文档和视觉效果制作&#xff0c;以及间接…

记录日志中logback和log4j2不能共存的问题

本文章记录设置两个日志时候&#xff0c;控制台直接报错 标黄处就是错误原因&#xff1a;1. SLF4J(W)&#xff1a;类路径包含多个SLF4J提供程序。 SLF4J(W)&#xff1a;找到提供程序[org.apache.logging.slf4j. net]。 SLF4J(W)&#xff1a;找到提供程序[ch.qos.log .classi…

【论文阅读】Virtual Compiler Is All You Need For Assembly Code Search

阅读笔记:Virtual Compiler Is All You Need For Assembly Code Search 1. 研究背景 逆向工程:逆向工程需要在庞大的二进制文件中快速定位特定功能(例如恶意行为)。传统方法依赖于经验和启发式算法,效率低下。汇编代码搜索:通过自然语言搜索汇编代码功能,能够更高效地处…

洛古---越狱问题【快速幂】

今天和大家讲一个洛古的算法题&#xff0c;我觉得还是比较有含金量的&#xff0c;今天给大家分享一下 题目描述 监狱有 &#x1d45b;n个房间&#xff0c;每个房间关押一个犯人&#xff0c;有 &#x1d45a; 种宗教&#xff0c;每个犯人会信仰其中一种。如果相邻房间的犯人的宗…

Python3.11.9+selenium,选择证书用多线程+键盘enter解决

Python3.11.9+selenium,选择证书用多线程+键盘enter解决 1、遇到问题:弹出证书选择,无法点击确定 import pyautogui pyautogui.press(enter) 键盘enter也无法点击 2、解决办法:用多线程解决同时执行click链接和Enter点击证书的确定 1、点击操作 # # 通过文本链接文本…

1、使用vscode+eide+stm32cubeMx开发stm32

步骤1&#xff1a;在vscode中安装如下的插件 步骤2&#xff1a;点击Embedded IDE&#xff0c;点击“新建项目”-----空项目-----Cortex-M项目。 步骤3&#xff1a;输入项目名&#xff0c;回车后会要制定保存路径&#xff0c;此时就是一个已项目名命名的文件夹。 步骤4&#xff…

网站小程序app怎么查有没有备案?

网站小程序app怎么查有没有备案&#xff1f;只需要官方一个网址就可以&#xff0c;工信部备案查询官网地址有且只有一个&#xff0c;百度搜索 "ICP备案查询" 找到官方gov.cn网站即可查询&#xff01; 注&#xff1a;网站小程序app备案查询&#xff0c;可通过输入单位…