【BFS 广度优先搜索】详解感染橘子最短时间问题

news2024/11/29 8:48:52

一、题目描述

在给定的 m x n 网格 grid 中,每个单元格可以有以下三个值之一:

  • 值 0 代表空单元格;
  • 值 1 代表新鲜橘子;
  • 值 2 代表腐烂的橘子。

每分钟,腐烂的橘子 周围 4 个方向上相邻 的新鲜橘子都会腐烂。

返回 直到单元格中没有新鲜橘子为止所必须经过的最小分钟数。如果不可能,返回 -1 。

示例

在这里插入图片描述

二、思路

总体思路 —— 肯定是对每个感染的橘橘,向四周感染,因此是广度优先搜索遍历

问题转化 ——求最短感染时间 ? nonono~~ 求的是 共可以感染多少层 后结束 (这就是最短时间)

代码实现思路: ——

  • 我们第一次把所有感染的橘子放在一起加入队列中,作为第一层
  • 然后我们把第一层的每个橘橘向四周感染,然后把第一层的橘橘移除队列,把感染后的橘橘加入队列,作为第二层
  • 对每一层的橘橘,如果其能向四周感染至少一个橘橘,就把结果 count++ (结果计数)—— 然后把这一层的感染橘橘的四周都感染一遍
  • 重复上述步骤,直至队列为空
  • 队列为空说明不能再往下感染了,然后我们判断还有没有没感染的橘橘,这样的橘橘永远不会被感染到(幸运的橘橘~~)

图解:

在这里插入图片描述

三、代码实现

1. 一些巧思

(1)队列中存放的元素

对存放每一层感染橘橘的队列,我们应该存放的是感染橘橘的坐标,但是这样很占用空间,因此优化如下:

—— 队列中元素为:temp = i * n + j ,其中 i 为橘橘所在行,j 为橘橘所在列,n 为每列多少个元素

—— 根据 i * n + j 反推得到当前橘橘所在的行与列

i = temp / n;
j = temp % n;

(2) 向当前感染橘橘四周搜索的代码

我们得到了当前的感染橘橘坐标为 x , y ,对向其四周搜索我们完全可以写四个方向,但是这样非常复杂,因此我们可以定义如下坐标跃迁数组:

        int[] rowStep = {-1, 1, 0, 0}; // 上下走
        int[] colStep = {0, 0, -1, 1}; // 左右走

这样在向四周遍历时,我们就可以通过如下的方式得到四个方向的坐标,并对其进行判断和相应操作:

          // 向四周遍历
          for(int k=0; k<4; k++){
          	  // 得到当前要遍历的坐标
              int x = xTemp + rowStep[k];
              int y = yTemp + colStep[k];
              if(x>=0 && x<m && y>=0 && y<n){ // 保证得到的坐标不越界
                  // 相应操作
                  // .....
              }
          }

2. 完整代码

题外话: 写这个代码时候,往二叉树的层次遍历去想,嘿嘿嘿,太像了不是嘛,就是一模一样鸭,就是对每层进行操作,二叉树的层次遍历是对每层中元素操作其左右节点,这个是操作其四周的节点,一模一样,一模一样了~

    // 994. 腐烂的橘子

    public int orangesRotting(int[][] grid) {
        int m = grid.length;
        int n = grid[0].length;
        int res = 0;
        int[] rowStep = {-1, 1, 0, 0}; // 上下走
        int[] colStep = {0, 0, -1, 1}; // 左右走
        // 初始化队列 —— 第一层
        Queue<Integer> queue = init(grid);
        // 广度优先搜索
        while(!queue.isEmpty()){
            // 当前层感染的橘橘数量
            int size = queue.size();
            // 是否含有新鲜的橘橘可以被感染
            boolean hasFresh = false;
            // 对当前层的每个感染的橘橘, 把它的周围都感染一圈
            for(int i=0; i<size; i++){
                int temp = queue.poll();
                int xTemp = temp / n;
                int yTemp = temp % n;

                // 感染该橘橘的上下左右
                for(int k=0; k<4; k++){
                    int x = xTemp + rowStep[k];
                    int y = yTemp + colStep[k];
                    if(x>=0 && x<m && y>=0 && y<n){
                        if(grid[x][y] == 1){
                            hasFresh = true; // 有可以感染的橘橘
                            grid[x][y] = 2;
                            queue.offer(x * n + y);
                        }
                    }
                }
            }

            if(hasFresh) res += 1; // 有可以感染的橘橘才结果才加一
        }
        if (hasFreshFinal(grid)) return -1;
        return res;
    }

    
    // 队列初始化 —— 加入所以感染的橘橘作为第一层
    public Queue<Integer> init(int[][] grid){
        Queue<Integer> queue = new LinkedList<>();
        int m = grid.length;
        int n = grid[0].length;
        for(int i=0; i<m; i++){
            for(int j=0; j<n; j++){
                if(grid[i][j] == 2){
                    queue.add(i * n + j);
                }
            }
        }
        return queue;
    }

    // 判断最后还有没有没感染的橘橘
    public Boolean hasFreshFinal(int[][] grid){

        int m = grid.length;
        int n = grid[0].length;
        for(int i=0; i<m; i++){
            for(int j=0; j<n; j++){
                if(grid[i][j] == 1){
                    return true;
                }
            }
        }
        return false;
    }

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

nginx在linux上的部署

第一步、虚拟机安装新建虚拟机&#xff08;创建的时候记得打开网络连接&#xff0c;使用nat转换的方式&#xff09;linux配置上网第一种方式&#xff1a;自动获取&#xff0c;将ipv4设置为dhcp的自动获取。但是这样每次获取的ip可能不一样。使用xshell连接的时候可能需要修改。…

第四十一讲:神州防火墙透明模式的初始配置

现在要求把防火墙接入到现有的局域网中&#xff0c;尽量不改变已有的LAN架构和IP 地址分配&#xff0c;还能对内网的流量管理进行管理&#xff0c;起到对内网的安全保护作用。防火墙接入要求&#xff0c;应该选择防火墙的工作模式为透明模式。透明模式对原有网络的介入最少&…

把PBP、前端对接、钉钉集成玩透的考试系统

文/刘俊良 周亮 年佳斌 编辑/杜逸敏 一、项目背景 客户需要开发一套企业内部的考试系统&#xff0c;用于企业内部规章制度的学习及考核。系统的主要功能包括&#xff1a; 每个员工都可以进行每日答题与专项答题。根据答题结果&#xff0c;归类不同的题库以供员工查询学习。…

进击的 AI 生成,创造性的新世界!

2022年&#xff0c;AI艺术生成文本生成图像的AI绘画生成器如雨后春笋般涌现&#xff0c;以一幅幅“不明觉厉”的AI作品进入大众视野。从2月Disco Diffusion爆火&#xff0c;仅两个月后OpenAI发布DALL-E 2&#xff0c;谷歌和Meta紧随其后宣布了各自的AI”画家“Imagen和Make-A-S…

尚医通-排班规则接口-排班详情接口-前端整合(二十五)

目录&#xff1a; &#xff08;1&#xff09;医院排班-排班规则接口 &#xff08;2&#xff09;医院排班-排班规则-前端整合 &#xff08;3&#xff09;医院排班-排班详情接口 &#xff08;4&#xff09;医院排班-排班详情前端整合 &#xff08;1&#xff09;医院排班-排班…

一文分析Linux虚拟化KVM-Qemu分析之内存虚拟化

说明&#xff1a; KVM版本&#xff1a;5.9.1QEMU版本&#xff1a;5.0.0工具&#xff1a;Source Insight 3.5&#xff0c; Visio 1. 概述 深入分析Linux虚拟化KVM-Qemu之ARMv8虚拟化文中描述过内存虚拟化大体框架&#xff0c;再来回顾一下&#xff1a; 非虚拟化下的内存的访问…

剑指 Offer 07. 重建二叉树

剑指 Offer 07. 重建二叉树 一、题目 输入某二叉树的前序遍历和中序遍历的结果&#xff0c;请构建该二叉树并返回其根节点。 假设输入的前序遍历和中序遍历的结果中都不含重复的数字。 Input: preorder [3,9,20,15,7], inorder [9,3,15,20,7] Output: [3,9,20,null,null,1…

ansible第三天作业

1.挂载本地光盘到/mnt 2.配置yum源仓库文件通过多种方式实现 仓库1 &#xff1a; Name: RH294_Base Description&#xff1a; RH294 base software Base urt: file:///mnt/BaseOS 不需要验证钦件包 GPG 签名 启用此软件仓库 仓库 2: Name: RH294_Stream Description …

QGIS编译---QGIS3.22.4 + Qt5.15.3 + VS2019 ---64位版本

0 编译结果 先放上编译结果&#xff1a; 图1 QGIS3.22 启动界面 图2 QGIS3.22 操作界面 1 前言 因一些主观、客观原因&#xff0c;一年多没更新博客了&#xff0c;提笔继续。 这是笔者编译的第三个版本QGIS&#xff0c;本次编译原因有四&#xff1a; &#xff08;1&#xff…

05-微服务调用组件FeignDubbo实战

JAVA 项目中如何实现接口调用 1&#xff09;Httpclient HttpClient 是 Apache Jakarta Common 下的子项目&#xff0c;用来提供高效的、最新的、功能丰富的支持 Http 协议的客户端编程工具包&#xff0c;并且它支持 HTTP 协议最新版本和建议。HttpClient 相比传统 JDK 自带的UR…

Neo4j图数据库实现节点批量删除

1 前言 1-1 简介 由于对图数据库需要经常维护&#xff0c;图数据库建设初期&#xff0c;需要经常对数据写入删除等操作。 1-2 任务背景 再将1100万数据写入Neo4j后&#xff0c;由于需要对每个实体的label做精细化处理&#xff0c;之前写入的时候每个实体的label全部都为‘Comm…

Webhook端口使用介绍与演示

在API接口调用的集成项目中&#xff0c;用户调用知行之桥的API接口以给EDI系统推送数据时&#xff0c;经常会有这样的疑问&#xff1a;怎样查看是否调用接口成功&#xff1f;怎样查看数据是否推送成功&#xff1f;推送之后用户端会有怎样的响应提示&#xff1f; 为满足以上问题…

个人资料、消息、书签和偏好设置 干货 | 环境问题还是测试的老大难?两个步骤轻松搞定

在实际的工作中&#xff0c;绝大部分公司都至少有3个以上的环境&#xff0c;供测试与研发人员使用。测试人员不可能为每个环境都准备一个自动化测试的脚本&#xff0c;这样的维护成本太过庞大。所以就需要做到一套脚本&#xff0c;可以在各个环境上面运行。首先在上一节提到过的…

并发编程——7.共享模型之工具

目录7.共享模型之工具7.1.线程池7.1.1.自定义线程池7.1.2.ThreadPoolExecutor7.1.2.1.线程池状态7.1.2.2.构造方法7.1.2.3.newFixedThreadPool7.1.2.4.newCachedThreadPool7.1.2.5.newSingleThreadExecutor7.1.2.6.提交任务7.1.2.7.关闭线程池7.1.2.9.异步模式之工作线程7.1.2.…

python之字符串分割

str.split() 是 Python 中字符串类型的一个方法&#xff0c;可以用来将字符串按照指定的分隔符分割成多个子字符串。 例如&#xff0c;如果你有一个字符串 ‘a,b,c,d’&#xff0c;你可以这样分割它&#xff1a; >>> a,b,c,d.split(,) [a, b, c, d]这会将字符串按照…

Web API的方法论及实践

文章目录前言基本原则构建步骤API 实践商品呈现初始的设计个性化&#xff0c;千人千面 & 可视化超前的设计监控遗漏的监控业务服务效率是第一生产力业务服务API样例服务配置ClientInfo“用完即走”的业务服务一个周末的辛劳无数个喝咖啡的悠闲时光总结参考资料前言 对于网…

EMQX+阿里云飞天洛神云网络 NLB:MQTT 消息亿级并发、千万级吞吐性能达成

随着物联网技术的发展与各行业数字化进程的推进&#xff0c;全球物联网设备连接规模与日俱增。一个可靠高效的物联网系统需要具备高并发、大吞吐、低时延的数据处理能力&#xff0c;支撑海量物联网数据的接入与分析&#xff0c;从而进一步挖掘数据价值。 于今年五月发布的 EMQ…

Java后端知识之代码混淆-避免反编译工具获取原码

java, 代码混淆, 编译, 反编译本文是向大家介绍java后端小知识&#xff0c;它能够实现编译后的class代码加密&#xff0c;能够避免使用反编译工具获取源码。本文介绍java代码编译成class后&#xff0c;怎么避免用反编译工具获取源码。编译简单先看一下java源码反编译就是针对编…

MCU-51:单片机蜂鸣器播放孤勇者

目录一、蜂鸣器介绍二、驱动电路2.1 三极管驱动2.2 集成电路驱动三、蜂鸣器播放音乐3.1 键盘与音符对照3.2 音符与频率对照四、孤勇者乐谱五、代码演示前面学习了 MCU-51&#xff1a;单片机蜂鸣器播放音乐和提示音我们知道了可以用51单片机播放乐谱今天我们用51单片机播放 孤勇…

修改NuGet包默认存放位置

默认情况下&#xff0c;NuGet下载的包存放在系统盘(C盘中)&#xff0c;这样一来&#xff0c;时间长了下载的包越多&#xff0c;C盘占用的空间也就越多。 1、问题描述 默认情况下&#xff0c;NuGet下载的包存放在系统盘(C盘中&#xff0c;一般在路径C:\Users\用户\.nuget\packag…