【算法】【优选算法】多源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

实测Gemini Pro:谷歌王牌AI,到底能帮我们解决多少实际问题?

实测Gemini Pro:谷歌王牌AI,到底能帮我们解决多少实际问题?

🔥草莓熊Lotso:个人主页 ❄️个人专栏: 《C++知识分享》《Linux 入门到实践:零基础也能懂》 ✨生活是默默的坚持,毅力是永久的享受! 🎬 博主简介: 文章目录 * 前言: * 一、核心亮点实测:不止是“多模态”,更是“真全能” * 1. 多模态处理:能“看、听、读、写”,还能“联动协作” * 2. 推理能力:复杂问题“会拆解、会纠错”,堪比专业助手 * 3. 代码能力:开发者的“全能帮手”,新手也能轻松上手 * 二、真实应用场景:这些领域,已经在用它提效了 * 1. 科研领域:帮研究员“节省时间”,专注核心工作 * 2. 内容创作:

By Ne0inhk
全球首个网页 MCP 发布 —— 亮数据 Bright Data AI+MCP 服务智能体教程

全球首个网页 MCP 发布 —— 亮数据 Bright Data AI+MCP 服务智能体教程

全球首个网页 MCP 发布 —— 亮数据 Bright Data AI+MCP 服务智能体教程 亮数据 Bright Data 正式发布全球首个网页 MCP(Model Context Protocol,模型上下文协议),这是人工智能与实时网络数据融合的重要里程碑。本文配套视频将带你快速上手,完整演示 AI+MCP 智能体的搭建过程。 全球首个网页 MCP 发布:亮数据MCP 文章目录 * 全球首个网页 MCP 发布 —— 亮数据 Bright Data AI+MCP 服务智能体教程 * 什么是网页 MCP? * 网页 MCP 的亮点特性 * 开发者支持方案 * 入门教程:5 分钟搭建 AI+MCP 智能体

By Ne0inhk
Vibe Coding范式实战:用AI工具链(Stitch+Figma+ai studio+Trae)快速开发全栈APP

Vibe Coding范式实战:用AI工具链(Stitch+Figma+ai studio+Trae)快速开发全栈APP

文章目录 * 概要 * stitch制作设计稿 * figma 原型展示 * ai studio 生成前端代码 * 基于trae + Supabase生成后端代码和数据库 * Github + vercel * pc端后台管理系统设计 概要 在 AI 技术深度渗透软件开发领域的当下,一种名为 “Vibe Coding”(氛围编程)的全新范式正在重塑开发者的工作方式。它的核心在于,开发者不再是逐行编写代码的 “码农”,而是通过自然语言描述意图、引导 AI 生成代码的 “创意引导者” 和 “结果验证者”,从而将精力聚焦于更高价值的产品设计和逻辑思考上。 本文提供一种 Vibe Coding 的工作模式:设计阶段以 Google Stitch 为起点,开发者通过文本或草图快速生成响应式 UI 设计与前端代码,再无缝导入 Figma 进行精细化视觉调整和原型设计,实现了从 “想法” 到

By Ne0inhk
告别SQL恐惧症:我用飞算JavaAI的SQL Chat,把数据库变成了“聊天室”

告别SQL恐惧症:我用飞算JavaAI的SQL Chat,把数据库变成了“聊天室”

摘要 对于许多开发者而言,与数据库打交道意味着繁琐的语法记忆、复杂的联表查询以及令人头疼的性能优化。你是否曾希望,能用说人话的方式直接操作数据库?飞算JavaAI专业版的SQL Chat功能,正是这样一个革命性的工具。本文将分享我如何将它变为一个永不疲倦的“数据库专家同事”,用自然语言轻松搞定一切数据需求。 一、 痛点切入:我们与SQL的“爱恨纠葛” 还记得那次惨痛的经历吗?新接手一个庞大项目,急需从几十张表中查询一份用户行为报表。你对着模糊的需求文档,在Navicat或DBeaver中艰难地敲打着JOIN、WHERE和GROUP BY,一遍遍执行、调试,生怕一个疏忽就拉垮了线上数据库。这不仅是技能的考验,更是对耐心和细心程度的终极折磨。 尤其是面对以下场景,无力感尤甚: * 复杂查询:涉及多表关联、嵌套子查询、窗口函数,SQL语句长得像一篇论文。 * 性能优化:一条SQL跑起来慢如蜗牛,却不知从何下手添加索引或改写。 * 老项目溯源:面对命名随意的表和字段,理解业务逻辑如同破译密码。 我们需要的不是一个更漂亮的SQL客户端,而是一个能理解我们意图的“智能数据库搭档”

By Ne0inhk