每日OJ题_多源BFS①_力扣542. 01 矩阵(多源BFS解决最短路原理)

2024-04-19 05:44

本文主要是介绍每日OJ题_多源BFS①_力扣542. 01 矩阵(多源BFS解决最短路原理),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

多源BFS解决最短路算法原理

力扣542. 01 矩阵

解析代码


多源BFS解决最短路算法原理

什么是单源最短路 / 多源最短路?

之前的BFS解决最短路都是解决的单源最短路。

画图来说,单源最短路问题即为:

而对于多源最短路问题:

如何解决此类题?

自然是利用多源BFS解决,下面提出解法:

        当我们将所有的源点作为一个源点来进行解题时,问题又变成了单源最短路问题,而为什么可以认为这种解法是正确的呢?

  • 感性的理解 :对于上图的ABC三点,显然A点到目标点的距离更远,当我们将其作为一个点时,A点就会被直接排除,此时该特殊源点实际上就是最近的源点的合并。

对于解法二,如何编写代码?

对于 单源最短路 问题的BFS解法为:

  • 将起始点加入到队列中,再进行一层一层的扩展

自然,对于 多源最短路 的BFS解法为:

  • 将所有的起始点加入到队列中,再进行一层一层的扩展

力扣542. 01 矩阵

542. 01 矩阵

难度 中等

给定一个由 0 和 1 组成的矩阵 mat ,请输出一个大小相同的矩阵,其中每一个格子是 mat 中对应位置元素到最近的 0 的距离。

两个相邻元素间的距离为 1 。

示例 1:

输入:mat = [[0,0,0],[0,1,0],[0,0,0]]
输出:[[0,0,0],[0,1,0],[0,0,0]]

示例 2:

输入:mat = [[0,0,0],[0,1,0],[1,1,1]]
输出:[[0,0,0],[0,1,0],[1,2,1]]

提示:

  • m == mat.length
  • n == mat[i].length
  • 1 <= m, n <= 10^4
  • 1 <= m * n <= 10^4
  • mat[i][j] is either 0 or 1.
  • mat 中至少有一个 
class Solution {
public:vector<vector<int>> updateMatrix(vector<vector<int>>& mat) {}
};

解析代码

对于求的最终结果,有两种方式:

  • 第一种方式:从每一个 1 开始,然后通过层序遍历找到离它最近的 0 。这一种方式,会以所有的 1 起点,来一次层序遍历,势必会遍历到很多重复的点。并且如果矩阵中只有一个 0 的话,每一次层序遍历都要遍历很多层,时间复杂度较高。
  • 第二种方式:正难则反,从 0 开始层序遍历,并且记录遍历的层数。当第一次碰到 1 的时候,当前的层数就是这个 1 离 0 的最短距离。

        第二种方式,在遍历的时候标记一下处理过的 1 ,能够做到只用历整个矩阵一次,就能得到最终结果。 但是有一个问题, 0 是有很多个的,怎么才能保证遇到的 1 距离这一个 0 是最近的呢?可以先把所有的 0 都放在队列中,把它们当成一个整体,每次把当前队列里面的所有元素向外扩展一次。可以开一个dist数组就能完成类似前面BFS解决最短路所需的bool数组,step和size变量:初始化成-1的话就是没遍历的,遍历的step只需在前一个格子加1,层数也能确定。

class Solution {int dx[4] = {0, 0, -1, 1};int dy[4] = {1, -1, 0, 0};
public:vector<vector<int>> updateMatrix(vector<vector<int>>& mat) {int m = mat.size(), n = mat[0].size();vector<vector<int>> dist(m, vector<int>(n, -1));queue<pair<int, int>> q;for(int i = 0; i < m; i++) // 把所有的源点加⼊到队列中{for(int j = 0; j < n; j++){if(mat[i][j] == 0){q.push({i, j});dist[i][j] = 0;}}}while(!q.empty()) // ⼀层⼀层往外扩{auto [a, b] = q.front();q.pop();for(int i = 0; i < 4; ++i){int x = a + dx[i], y = b + dy[i];if(x >= 0 && x < m && y >= 0 && y < n && dist[x][y] == -1){dist[x][y] = dist[a][b] + 1;q.push({x, y});}}}return dist;}
};

也可以不开空间直接在原数组操作:

class Solution {int dx[4] = {0, 0, -1, 1};int dy[4] = {1, -1, 0, 0};
public:vector<vector<int>> updateMatrix(vector<vector<int>>& mat) {int m = mat.size(), n = mat[0].size();queue<pair<int, int>> q;for(int i = 0; i < m; i++) // 把所有的源点加⼊到队列中{for(int j = 0; j < n; j++){if(mat[i][j] == 0)q.push({i, j});elsemat[i][j] = -1;}}while(!q.empty()) // ⼀层⼀层往外扩{auto [a, b] = q.front();q.pop();for(int i = 0; i < 4; ++i){int x = a + dx[i], y = b + dy[i];if(x >= 0 && x < m && y >= 0 && y < n && mat[x][y] == -1){mat[x][y] = mat[a][b] + 1;q.push({x, y});}}}return mat;}
};

这篇关于每日OJ题_多源BFS①_力扣542. 01 矩阵(多源BFS解决最短路原理)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/916753

相关文章

Spring Boot Interceptor的原理、配置、顺序控制及与Filter的关键区别对比分析

《SpringBootInterceptor的原理、配置、顺序控制及与Filter的关键区别对比分析》本文主要介绍了SpringBoot中的拦截器(Interceptor)及其与过滤器(Filt... 目录前言一、核心功能二、拦截器的实现2.1 定义自定义拦截器2.2 注册拦截器三、多拦截器的执行顺序四、过

解决idea启动项目报错java: OutOfMemoryError: insufficient memory

《解决idea启动项目报错java:OutOfMemoryError:insufficientmemory》:本文主要介绍解决idea启动项目报错java:OutOfMemoryError... 目录原因:解决:总结 原因:在Java中遇到OutOfMemoryError: insufficient me

maven异常Invalid bound statement(not found)的问题解决

《maven异常Invalidboundstatement(notfound)的问题解决》本文详细介绍了Maven项目中常见的Invalidboundstatement异常及其解决方案,文中通过... 目录Maven异常:Invalid bound statement (not found) 详解问题描述可

Java 队列Queue从原理到实战指南

《Java队列Queue从原理到实战指南》本文介绍了Java中队列(Queue)的底层实现、常见方法及其区别,通过LinkedList和ArrayDeque的实现,以及循环队列的概念,展示了如何高效... 目录一、队列的认识队列的底层与集合框架常见的队列方法插入元素方法对比(add和offer)移除元素方法

SQL 注入攻击(SQL Injection)原理、利用方式与防御策略深度解析

《SQL注入攻击(SQLInjection)原理、利用方式与防御策略深度解析》本文将从SQL注入的基本原理、攻击方式、常见利用手法,到企业级防御方案进行全面讲解,以帮助开发者和安全人员更系统地理解... 目录一、前言二、SQL 注入攻击的基本概念三、SQL 注入常见类型分析1. 基于错误回显的注入(Erro

Spring IOC核心原理详解与运用实战教程

《SpringIOC核心原理详解与运用实战教程》本文详细解析了SpringIOC容器的核心原理,包括BeanFactory体系、依赖注入机制、循环依赖解决和三级缓存机制,同时,介绍了SpringBo... 目录1. Spring IOC核心原理深度解析1.1 BeanFactory体系与内部结构1.1.1

nacos服务无法注册到nacos服务中心问题及解决

《nacos服务无法注册到nacos服务中心问题及解决》本文详细描述了在Linux服务器上使用Tomcat启动Java程序时,服务无法注册到Nacos的排查过程,通过一系列排查步骤,发现问题出在Tom... 目录简介依赖异常情况排查断点调试原因解决NacosRegisterOnWar结果总结简介1、程序在

解决java.util.RandomAccessSubList cannot be cast to java.util.ArrayList错误的问题

《解决java.util.RandomAccessSubListcannotbecasttojava.util.ArrayList错误的问题》当你尝试将RandomAccessSubList... 目录Java.util.RandomAccessSubList cannot be cast to java.

java反序列化serialVersionUID不一致问题及解决

《java反序列化serialVersionUID不一致问题及解决》文章主要讨论了在Java中序列化和反序列化过程中遇到的问题,特别是当实体类的`serialVersionUID`发生变化或未设置时,... 目录前言一、序列化、反序列化二、解决方法总结前言serialVersionUID变化后,反序列化失

MySQL 批量插入的原理和实战方法(快速提升大数据导入效率)

《MySQL批量插入的原理和实战方法(快速提升大数据导入效率)》在日常开发中,我们经常需要将大量数据批量插入到MySQL数据库中,本文将介绍批量插入的原理、实现方法,并结合Python和PyMySQ... 目录一、批量插入的优势二、mysql 表的创建示例三、python 实现批量插入1. 安装 PyMyS