【算法】【优选算法】多源BFS

【算法】【优选算法】多源BFS

目录

一、多源BFS

单源最短路:只有一个起点到终点的最短路问题。
多源最短路问题:有多个起点到终点的最短路问题。
多源BFS:用BFS来解决边权相同的多源最短路问题。

解法:

  1. 暴力解题,把多源最短路问题,转化为若干个单源最短路问题。
  2. 把所有起点当成一个起点,问题就变成了单源最短路问题。

二、542.01 矩阵

题目链接:542.01 矩阵

题目描述:

题目解析:

  • 给一个只有0 1 的二维数组,计算其中每一个元素到0的最短距离,自己是0距离就是0,将距离存入一个相同规模二维数组的下标中。

法一:
解题思路:

  • 我们如果遍历数组,找到1后,就进行求该元素到0的最短距离。
  • 求最短距离就使用前面求权值相同的最短距离的方法即可。
  • 但是会超时。
    解题代码:
//时间复杂度:O(M*N*M*N)//空间复杂度:O(M*N)classSolution{int[] dx ={0,0,1,-1};int[] dy ={1,-1,0,0};int m,n;publicint[][]updateMatrix(int[][] mat){ m = mat.length; n = mat[0].length;int[][] ret =newint[m][n];//遍历mat,遍历到1找最近的0,for(int i =0; i < m; i++){for(int j =0; j < n; j++){if(0== mat[i][j]){ ret[i][j]=0;}else{ ret[i][j]=bfs(mat,i,j);}}}return ret;}publicintbfs(int[][] mat,int x,int y){Queue<int[]> queue =newLinkedList<>(); queue.add(newint[]{x,y});boolean[][] flag =newboolean[m][n]; flag[x][y]=true;int ret =0;while(!queue.isEmpty()){ ret++;int size = queue.size();while(size--!=0){int[] arr = queue.poll();for(int i =0; i <4; i++){int a = arr[0]+ dx[i];int b = arr[1]+ dy[i];//入队if(a >=0&& a < m && b >=0&& b < n &&!flag[a][b]&& mat[a][b]!=0){ flag[a][b]=true; queue.add(newint[]{a,b});}//结束条件if(a >=0&& a < m && b >=0&& b < n && mat[a][b]==0)return ret;}}}return0;}}

法二:
解题思路:

  • 我们先将数组中的所有0下标,记录下来放入队列中。
  • 然后我们层序遍历,每一次循环遍历完当前队列中的值,往外BFS寻找没被标记的1,寻找的循环次数就是这个1的最短距离。

解题代码:

//时间复杂度:O(M*N)//空间复杂度:O(M*N)classSolution{int[] dx ={0,0,1,-1};int[] dy ={1,-1,0,0};publicint[][]updateMatrix(int[][] mat){int m = mat.length;int n = mat[0].length;int[][] ret =newint[m][n];boolean[][] flag =newboolean[m][n];Queue<int[]> queue =newLinkedList<>();//遍历mat,先把0全部放入队列,for(int i =0; i < m; i++){for(int j =0; j < n; j++){if(0== mat[i][j]){ queue.add(newint[]{i,j}); ret[i][j]=0;}}}//遍历队列中的元素,层序递进int tep =0;while(!queue.isEmpty()){ tep++;int size = queue.size();while(size--!=0){int[] arr = queue.poll();for(int i =0; i <4; i++){int x = arr[0]+ dx[i];int y = arr[1]+ dy[i];//入队if( x >=0&& x < m && y >=0&& y < n &&1== mat[x][y]&&!flag[x][y]){ flag[x][y]=true; queue.add(newint[]{x,y}); ret[x][y]= tep;}}}}return ret;}}

改进:

  • 我们就可以直接使用结果数组,来达到上面的flag数组的记录功能,也不再需要记录层数。
  • 我们将mat数组中元素为1对应的ret结果数组元素记录为-1;
  • 当我们BFS的时候,如果ret元素为-1,那么证明没有记录过,那么这个元素值就是出队列元素对应的ret值加一;
  • 当ret中数组元素没有-1了就会结束。
//时间复杂度:O(M*N)//空间复杂度:O(M*N)classSolution{int[] dx =newint[]{0,0,1,-1};int[] dy =newint[]{1,-1,0,0};publicint[][]updateMatrix(int[][] mat){int m = mat.length;int n = mat[0].length;int[][] ret =newint[m][n];Queue<int[]> queue =newLinkedList<>();for(int i =0; i < m; i++){for(int j =0; j < n; j++){ ret[i][j]=-1;if(mat[i][j]==0){ queue.add(newint[]{i,j}); ret[i][j]=0;}}}while(!queue.isEmpty()){int[] arr = queue.poll();for(int i =0; i <4; i++){int x = arr[0]+ dx[i];int y = arr[1]+ dy[i];//入队if(x >=0&& x < m && y >=0&& y < n && ret[x][y]==-1){ queue.add(newint[]{x,y}); ret[x][y]= ret[arr[0]][arr[1]]+1;}}}return ret;}}

三、1020.⻜地的数量

题目链接:1020.⻜地的数量

题目描述:

题目解析:

  • 给我们一个只有0 1 的数组,让我们统计(上下左右)连成块的1,并且这其中1没有在数组边的个数。

解题思路:

  • 我们使用标记数组标记 0 和 处于边上的 1
  • 将边上 1 的坐标放入队列
  • 在对队列中的元素实行BFS,入队条件是没被标记的元素。
  • 执行完BFS,就只会有符合条件的1 没有被标记。
  • 我们使用数组元素个数作为返回值,标记一次返回值就减1,最后就是所求值。

解题代码:

//时间复杂度:O(M*N)//空间复杂度:O(M*N)classSolution{int[] dx =newint[]{0,0,1,-1};int[] dy =newint[]{1,-1,0,0};publicintnumEnclaves(int[][] grid){int m = grid.length;int n = grid[0].length;Queue<int[]> queue =newLinkedList<>();boolean[][] flag =newboolean[m][n];//先将所有边界1入队并标记,将0标记int ret = m * n;for(int i =0; i < m; i++){for(int j =0; j < n; j++){if(grid[i][j]==1&&(i ==0|| i == m -1|| j ==0|| j == n -1)){ queue.add(newint[]{i,j}); flag[i][j]=true; ret--;}elseif(grid[i][j]==0){ flag[i][j]=true; ret--;}}}while(!queue.isEmpty()){int[] arr = queue.poll();for(int i =0; i <4; i++){int x = arr[0]+ dx[i];int y = arr[1]+ dy[i];if(x >=0&& x < m && y >=0&& y < n &&!flag[x][y]){ ret--; queue.add(newint[]{x,y}); flag[x][y]=true;}}}return ret;}}

四、1765. 地图中的最⾼点

题目链接:1765. 地图中的最⾼点

题目描述:

题目解析:

  • 给我们一个数组,其中1代表水域,0代表陆地。
  • 要求返回一个height高度数组,数组元素比上下左右元素高度差不超过一。返回能使height元素达到最大值的结果。

解题思路:

  • 我们先将水域入队,然后从水域元素往外扩,将四周元素入队,并且使其height值比让他入队的元素大1
  • 每个元素只能入一次对列,我们要有标技数组,我们可以直接使用height为标记数组,初始化时将陆地元素赋值-1,只要是值不是-1的元素就证明入过对列了。

解题代码:

//时间复杂度:O(M*N)//空间复杂度:O(M*N)classSolution{int[] dx =newint[]{0,0,1,-1};int[] dy =newint[]{1,-1,0,0};publicint[][]highestPeak(int[][] isWater){int m = isWater.length;int n = isWater[0].length;int[][] height =newint[m][n];Queue<int[]> queue =newLinkedList<>();//遍历isWater数组,1水域对应height为0,并入对,其余为-1,起标记作用for(int i =0; i < m; i++){for(int j =0; j < n; j++){ height[i][j]=-1;if(isWater[i][j]==1){ height[i][j]=0; queue.add(newint[]{i,j});}}}//BFSwhile(!queue.isEmpty()){int[] arr = queue.poll();for(int i =0; i <4; i++){int x = arr[0]+ dx[i];int y = arr[1]+ dy[i];//height为-1入队,值为出队列元素加1if(x >=0&& x < m && y >=0&& y < n && height[x][y]==-1){ height[x][y]= height[arr[0]][arr[1]]+1; queue.add(newint[]{x,y});}}}return height;}}

五、1162. 地图分析

题目链接:1162. 地图分析

题目描述:

题目解析:

  • 给我们一个grid数组,只有0 1
  • 找出 0 通过上下左右走到最近的1 的距离的最大值

解题思路:

  • 一个最经典的多源BFS
  • 我们从1开始走(将1全部入队),每走一次(将当前队列元素出完,将元素上下左右的没标记过的0入队),直到走完所有元素,最后走的次数就是结果。
    解题代码:
//时间复杂度:O(M*N)//空间复杂度:O(M*N)classSolution{int[] dx =newint[]{0,0,1,-1};int[] dy =newint[]{1,-1,0,0};publicintmaxDistance(int[][] grid){int m = grid.length;int n = grid[0].length;int ret =0;Queue<int[]> queue =newLinkedList<>();boolean[][] flag =newboolean[m][n];//所有1入队for(int i =0; i < m; i++){for(int j =0; j < n; j++){if(grid[i][j]==1){ queue.add(newint[]{i,j}); flag[i][j]=true; ret++;}}}//判断是否全0或全1if(ret ==0|| ret == m * n)return-1; ret =-1;//BFSwhile(!queue.isEmpty()){int size = queue.size(); ret++;while(size--!=0){int[] arr = queue.poll();for(int i =0; i <4; i++){int x = arr[0]+ dx[i];int y = arr[1]+ dy[i];//入队if(x >=0&& x < m && y >=0&& y < n &&!flag[x][y]&& grid[x][y]==0){ queue.add(newint[]{x,y}); flag[x][y]=true;}}}}return ret;}}

Read more

【Python基础】(五)Python 库使用全攻略:从标准库到第三方库,让开发效率翻倍

【Python基础】(五)Python 库使用全攻略:从标准库到第三方库,让开发效率翻倍

目录 编辑 前言 一、Python 库的核心认知:什么是库?为什么要用库? 1.1 库的本质:现成的 "代码工具箱" 1.2 库的分类:标准库 vs 第三方库 (1)标准库:Python 自带的 "基础工具箱" (2)第三方库:全球开发者共建的 "扩展工具箱" 1.3 使用库的核心优势:效率翻倍的关键 二、标准库实战:内置工具的高效用法 2.1 日期时间处理:datetime库(计算日期差、格式转换) 实战需求:计算你和心爱的人认识多少天 扩展用法:

By Ne0inhk
Python 基础与环境配置

Python 基础与环境配置

第一篇:Python 基础与环境配置 学习目标 💡 掌握 Python 语言的基本语法和编程思想 💡 学会安装和配置 Python 开发环境 💡 理解并熟练运用 Python 的数据类型、变量和运算符 💡 掌握 Python 的流程控制语句(条件判断、循环) 💡 学会使用 Python 的函数和模块 💡 了解 Python 的常用开发工具和集成开发环境(IDE) 💡 具备编写简单 Python 程序的能力 重点内容 * Python 语言的发展历程与特点 * Python 开发环境的安装与配置 * Python 的基本语法(变量、数据类型、运算符) * 流程控制语句(if 语句、for 循环、while 循环) * 函数的定义、调用和参数传递 * 模块和包的使用 * 常用开发工具和

By Ne0inhk
在 macOS 下升级 Python 几种常见的方法

在 macOS 下升级 Python 几种常见的方法

在 macOS 下升级 Python 有几种常见的方法,具体取决于你最初是如何安装 Python 的。了解你的安装方式是关键。 首先,你需要知道你当前 Python 版本以及它的安装路径。 1. 检查 Python 版本: python --version# 可能指向 Python 2.x python3 --version# 通常指向 Python 3.x 2. 检查 Python 路径: which python which python3 根据你 which 命令的输出,我们可以推断出安装方式。常见的安装方式有: * macOS 系统自带 Python: 通常在 /usr/bin/python。不建议直接修改或升级系统自带的

By Ne0inhk
Python智慧农业信息化服务平台农产品商城系统 小程序

Python智慧农业信息化服务平台农产品商城系统 小程序

文章目录 * 技术架构设计 * 核心功能模块 * 物联网数据整合 * 性能优化策略 * 安全防护措施 * 部署与监控 * 系统设计与实现的思路 * 主要技术与实现手段 * 源码lw获取/同行可拿货,招校园代理 :文章底部获取博主联系方式! 技术架构设计 * 前端框架:采用微信小程序原生框架+WXML/WXSS,结合Vant Weapp组件库快速搭建UI界面。 * 后端服务:基于Django REST Framework构建API,支持JWT身份认证与RBAC权限控制。 * 数据库:MySQL存储业务数据,Redis缓存高频访问数据(如商品详情、用户会话)。 * 消息队列:使用RabbitMQ处理异步任务(如订单状态更新、消息推送)。 核心功能模块 * 用户系统:OpenID自动注册/登录,农户与消费者角色分离,个人中心集成实名认证模块。 * 商品管理:支持多级分类、动态SKU、溯源信息(区块链哈希值存储)。 * 订单系统:微信支付接口对接,物流状态实时同步(调用快递鸟API)。 智能推荐:

By Ne0inhk