算法系列--多源BFS问题

news2024/11/17 15:49:32

💕"对相爱的人来说,对方的心意,才是最好的房子。"💕
作者:Lvzi
文章主要内容:算法系列–多源BFS问题
在这里插入图片描述

大家好,今天为大家带来的是算法系列--多源BFS问题

前言:
之前我们已经学习过单源的最短路问题,核心就是通过bfs实现来记录最短的路径,解题步骤如下:

  1. 将起点添加进队列–q.add(start)
  2. 一层一层往外扩展(step++)

所谓的多源最短路问题就是有多个起点的最短路问题,如何解决呢?相信大家的第一想法是:不就是多个起点么,每个起点我都做一次单源的最短路问题,再返回结果中最小的不就行了么,这种做法当然是可以的,但是时间复杂度过高,下面讲解第二种方法–超源起点

超源起点就是将所有的起点当做一个起点,以这个点为起点到终点之间的路径就是最短路,从感性上讲为什么这种策略是对的呢?假设我们现在有三个起点,则最短的路径一定是在以这三个点为起点的最短路径之中,则最后求出的一定是最短路径
在这里插入图片描述

这样我们就将多源的最短路问题转化为单源的最短路问题!解法同单源最短路问题,下面是leetocode上比较经典的多源bfs问题

一.01 矩阵(medium)

题目链接:
01 矩阵(medium)
在这里插入图片描述

分析:

转化为从0到1的最短路问题

代码:

// 正难则反的思想
// 将0看作起点,1看做终点  转化为从0-1的最短路问题
class Solution {
    int[] dx = { 1, -1, 0, 0 };
    int[] dy = { 0, 0, 1, -1 };

    public int[][] updateMatrix(int[][] mat) {
        int m = mat.length, n = mat[0].length;
        int[][] dist = new int[m][n];
        Queue<int[]> q = new LinkedList<>();

        // 将所有起点添加进入队列之中
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (mat[i][j] != 0)
                    dist[i][j] = -1;// 将不是起点的位置全部初始化为-1
                if (mat[i][j] == 0)
                    q.add(new int[] { i, j });// 将所有的起点添加进队列之中
            }
        }

        // 多源bfs
        while (!q.isEmpty()) {
            int[] t = q.poll();
            int a = t[0], b = t[1];
            for (int i = 0; i < 4; i++) {
                int x = a + dx[i], y = b + dy[i];
                if (x >= 0 && y >= 0 && x < m && y < n && dist[x][y] == -1) {
                    q.add(new int[] { x, y });
                    dist[x][y] = dist[a][b] + 1;
                }
            }
        }

        return dist;
    }
}

总结:
两个小优化的地方:在单源bfs问题之中,我们经常使用三个变量

  • boolean[][] vis:用于标记是否被搜索过
  • int step:用于记录当前的层数(路径长度)
  • int sz:当前层一共有多少个节点

但是在本题中这三个变量都不存在,实际上是通过其他方式来替代了:

  • 将dist数组中不是起点的位置初始化为-1–替代了vis的作用,在判断时,只需判断dist[x][y]是否等于-1即可,如果等于证明没有被搜索过
  • 由于我们在往外扩展的时候是一步一步往外扩展的,dist[a][b]存储的就是走到当前层所需的最小步数,那么以a,b为起点的下一层的所有位置的步数全部都是dist[a][b] + 1的值,不需要通过step来记录路径长度,且也不需要sz来保证是同一层(只要dist[a][b]相同,就是同一层)

二.⻜地的数量

题目链接:⻜地的数量
在这里插入图片描述

分析:

和被围绕的区域类似,这里用的是多源bfs

代码:

// 1.将边界上所有的1添加进入队列
// 2.将所有的联通块(1)标记为0
// 3.统计1的数目,返回即可
class Solution {
    int[] dx = {1,-1,0,0};
    int[] dy = {0,0,1,-1};
    boolean[][] vis;
    public int numEnclaves(int[][] grid) {
        int m = grid.length, n = grid[0].length;
        vis = new boolean[m][n];
        Queue<int[]> q = new LinkedList<>();
		// 将边界上所有的1添加进入队列
        for(int i = 0; i < m; i++) {
            if(grid[i][0] == 1) q.add(new int[]{i,0});
            if(grid[i][n - 1] == 1) q.add(new int[]{i,n - 1});
        }

        for(int j = 0; j < n; j++) {
            if(grid[0][j] == 1) q.add(new int[]{0,j});
            if(grid[m - 1][j] == 1) q.add(new int[]{m - 1, j});
        }

        // 多源bfs  将所有的联通块1标记为0
        while(!q.isEmpty()) {
            int[] t = q.poll();
            int a = t[0], b = t[1];
            grid[a][b] = 0;

            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 && grid[x][y] == 1) {
                    q.add(new int[]{x, y});
                    grid[x][y] = 0;
                }
            }
        }

        int ret = 0;
        for(int i = 0; i < m; i++) 
            for(int j = 0; j < n; j++)
                if(grid[i][j] == 1) ret++;

        return ret;
    }
}

三.地图中的最⾼点

题目链接:地图中的最⾼点
在这里插入图片描述
在这里插入图片描述

分析:

多源bfs

代码:

// 和矩阵那道题目相同
class Solution {
    int[] dx = {1,-1,0,0};
    int[] dy = {0,0,1,-1};
    public int[][] highestPeak(int[][] isWater) {
        int m = isWater.length, n = isWater[0].length;
        int[][] height = new int[m][n];
        Queue<int[]> q = new LinkedList<>();
        for(int i = 0; i < m; i++) {
            for(int j = 0; j < n; j++) {
                if(isWater[i][j] == 1) {
                    q.add(new int[]{i, j});// 将水域添加进队列
                }else {
                    height[i][j] = - 1;// 陆地置为-1
                }
            }
        }

        // 多源bfs
        while(!q.isEmpty()) {
            int[] t = q.poll();
            int a = t[0], b = t[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 && height[x][y] == -1) {
                    q.add(new int[]{x, y});
                    height[x][y] = height[a][b] + 1;
                }
            }
        }

        return height;
    }
}

四.地图分析

题目链接:地图分析
在这里插入图片描述

分析:

多源bfs + 更新最值
以海洋为起点计算到陆地的最短距离比较困难(无法确定是哪一个海洋)
所以改为以陆地为起点,计算其到海洋的距离

代码:

class Solution {
    int[] dx = {1,-1,0,0};
    int[] dy = {0,0,1,-1};
    public int maxDistance(int[][] grid) {
        int n = grid.length, ret = 0;
        int[][] dist = new int[n][n];
        Queue<int[]> q = new LinkedList<>();

        boolean flg = false;
        for(int i = 0; i < n; i++) {
            for(int j = 0; j < n; j++) {
                if(grid[i][j] == 1) q.add(new int[]{i, j});// 将陆地当做起点
                else {
                    dist[i][j] = -1;// 将所有海洋置为-1
                    flg = true;// 存在海洋
                }
            }
        }

        if(q.size() == 0) return -1;// 全是海洋
        if(!flg) return -1;// 全是陆地

        // 多源bfs
        while(!q.isEmpty()) {
            int[] t = q.poll();
            int a = t[0], b = t[1];
            for(int k = 0; k < 4; k++) {
                int x = a + dx[k], y = b + dy[k];
                if(x >= 0 && y >= 0 && x < n && y < n && dist[x][y] == -1) {
                    q.add(new int[]{x, y});
                    dist[x][y] = dist[a][b] + 1;
                    ret = Math.max(ret, dist[x][y]);// 更新最值
                }
            }
        }

        return ret;
    }
}

五.总结

  • 多源bfs最常用的一个思想就是正难则反,这个思想主要用于解决谁是起点,谁是终点的问题
  • 多源bfs问题的代码 比较固定

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

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

相关文章

质谱原理与仪器3-笔记

质谱原理与仪器3-笔记 一、质量分析器类型1、聚焦磁场分析器&#xff1a;A、单聚焦磁场分析器B、双聚焦磁场分析器 2、四极杆质量分析器3、飞行时间质谱仪(Time of Flight MS, TOF-MS)4、离子阱质量分析器 二、质谱仪的主要性能指标1、质量范围(mass range)2、分辨率(resolutio…

面试经典150题——Z 字形变换

面试经典150题 day22 题目来源我的题解方法一 使用StringBuilder数组模拟矩阵方法二 找规律直接构造 题目来源 力扣每日一题&#xff1b;题序&#xff1a;6 我的题解 方法一 使用StringBuilder数组模拟矩阵 如果numRows是1&#xff0c;则直接返回s。 否则&#xff0c;创建nu…

python实现的基于单向循环链表插入排序

相比于定义一个循环双向链表来实现插入排序来说&#xff0c;下面的实现采用一个单向循环链表来实现&#xff0c;并且不需要定义一个单向循环链表类&#xff0c;而是把一个list&#xff08;数组/顺序表&#xff09;当成单向循环链表来用&#xff0c;list的元素是一个包含两个元素…

26.统一网关Gateway

网关的功能 1.身份认证&#xff0c;权限的校验。 2.服务的路由&#xff0c;负载均衡。用户请求被分配到哪一个微服务。一个微服务可以有多个实例&#xff0c;所以使用负载均衡。 3.请求限流。 springcloud网关实现有两种&#xff1a;gateway, zuul zuul是基于servlet实现的…

Enhancing Diffusion——利用三维透视几何约束增强扩散模型

概述 透视在艺术中被广泛研究&#xff0c;但现代高质量图像生成方法却缺乏透视精度。新的生成模型引入了几何约束&#xff0c;通过训练过程提高透视精度。这样可以生成更逼真的图像&#xff0c;并提高相关深度估计模型的性能。 最近的图像生成技术使研究人员能够创造性地进行…

TCP/IP和HTTP协议

TCP/IP OSI 七层模型在提出时的出发点是基于标准化的考虑&#xff0c;而没有考虑到具体的市场需求&#xff0c;使得该模型结构复杂&#xff0c;部分功能冗余&#xff0c;因而完全实现 OSI 参考模型的系统不多。而 TCP/IP 参考模型直接面向市场需求&#xff0c;实现起来也比较…

App一键直达,Xinstall助力提升用户体验

在这个移动互联网时代&#xff0c;App已经成为了我们日常生活中不可或缺的一部分。然而&#xff0c;每当我们在浏览器或社交平台上看到一个有趣的App推荐&#xff0c;点击下载后却往往要经历一系列繁琐的跳转和确认过程&#xff0c;这无疑大大降低了用户体验。那么&#xff0c;…

工业三废数据集(工业烟粉尘排放量、工业二氧化硫排放量、工业废水排放量)2006-2021年

01、数据介绍 工业三废是指工业生产过程中排出的废气、废水和废渣 工业二氧化硫排放量指企业在燃料燃烧和生产工艺过程中排入大气的二氧化硫数量。 工业烟粉尘排放量是指企业在生产工艺过程中排放的烟尘和粉尘等颗粒物重量。 工业废水排放量是指企业在生产过程中产生的废水…

GPG的使用

这里写自定义目录标题 安装加密程序生成加密密钥怎么备份自己的密钥就可以使用公钥加密邮件信息了 安装加密程序 下载gpg4win&#xff1a; https://www.gpg4win.org/index.html 免费的&#xff0c;如果使用的是苹果电脑&#xff0c;使用https://gpgtools.org/。 如果是linux&a…

Go Web 开发基础【用户登录、注册、验证】

前言 这篇文章主要是学习怎么用 Go 语言&#xff08;Gin&#xff09;开发Web程序&#xff0c;前端太弱了&#xff0c;得好好补补课&#xff0c;完了再来更新。 1、环境准备 新建项目&#xff0c;生成 go.mod 文件&#xff1a; 出现报错&#xff1a;go: modules disabled by G…

【webrtc】RemoteAudioSource的创建线程

m98 代码&#xff1a;I:\webrtc m98_yjf\src\pc\rtp_transmission_manager.cc RtpTransmissionManager::CreateReceiver 在信令线程创建receiver receiver 是&#xff1a; rtc::scoped_refptr<RtpReceiverProxyWithInternal<RtpReceiverInternal>>receiver;其实际…

uniapp微信小程序开发踩坑日记:由于图表数据渲染不出来,我第一次在项目中用watch函数监听数据变化

一、发现问题 在我们团队自己开发的微信小程序中&#xff0c;引入了Echarts图表库 然后突然有一天&#xff0c;后端队友反应图表渲染有问题。后面我去试了一下&#xff0c;确实20次里面必有一次数据渲染不出来 断定代码没问题&#xff0c;于是我们将其鉴定为玄学 二、问题原因…

笔记本无线网络共享给有线使用

1.鼠标右击wifi图标选择打开网络和Internet设置 2.选择WLAN项&#xff0c;点击进入更改适配器选项 3.进入到以下界面&#xff0c;右击以太网选择启动&#xff08;不确定的话可以在设备管理器查看网卡&#xff09; 4.右击WLAN选项&#xff0c;点击属性 5.点击共享&#xff0…

日期类的实现,const成员

目录 一&#xff1a;日期类实现 二&#xff1a;const成员 三&#xff1a;取地址及const取地址操作符重载 一&#xff1a;日期类实现 //头文件#include <iostream> using namespace std;class Date {friend ostream& operator<<(ostream& out, const Dat…

AI大模型探索之路-训练篇9:大语言模型Transformer库-Pipeline组件实践

系列篇章&#x1f4a5; AI大模型探索之路-训练篇1&#xff1a;大语言模型微调基础认知 AI大模型探索之路-训练篇2&#xff1a;大语言模型预训练基础认知 AI大模型探索之路-训练篇3&#xff1a;大语言模型全景解读 AI大模型探索之路-训练篇4&#xff1a;大语言模型训练数据集概…

大连宇都环境 | 成都5月水科技大会暨技术装备成果展览会

中华环保联合会水环境治理专业委员会 秘书处 王小雅 13718793867 —— 展位号&#xff1a;A09 —— 一、企业介绍 大连宇都环境成立于2002年&#xff0c;公司20年 MBBR填料产品及工艺技术&#xff0c;&#xff0c;构建了研发、制造、设计、工程、运营链式服务能力&#xff…

CGAL 点云数据生成DSM、DTM、等高线和数据分类

原文链接 CGAL 点云数据生成DSM、DTM、等高线和数据分类 - 知乎 在GIS应用软件中使用的许多传感器(如激光雷达)都会产生密集的点云。这类应用软件通常利用更高级的数据结构&#xff1a;如&#xff1a;不规则三角格网 (TIN)是生成数字高程模型 (DEM) 的基础&#xff0c;也可以利…

docker系列8:容器卷挂载(上)

传送门 docker系列1&#xff1a;docker安装 docker系列2&#xff1a;阿里云镜像加速器 docker系列3&#xff1a;docker镜像基本命令 docker系列4&#xff1a;docker容器基本命令 docker系列5&#xff1a;docker安装nginx docker系列6&#xff1a;docker安装redis docker系…

1.初探MPI——MPI简介

系列文章目录 初探MPI——MPI简介初探MPI——点对点通信初探MPI——集体通信 文章目录 系列文章目录前言一、MPI_COMM_WORLD, size and ranks二、Hello WorldInstructions 总结参考 前言 Message Passing Interface (MPI) 是一种标准化的消息传递库接口规范。该标准是消息传递…

结构体的对齐原则

一、C语言结构体对齐步骤: 1.每个成员对齐 2.总体对齐 二、C语言结构体对齐规则: 1.结构体第一个成员存放在相较于结构体变量起始位置的偏移量为0的位置 2.从第二个成员开始&#xff0c;往后的每一个成员都要对齐到某个对齐数的整数倍处。 对齐数&#xff1a;结构体成员自身的…