Leetcode 542:01 矩阵 01 Matrix### 题目:

给定一个由 0 和 1 组成的矩阵,找出每个元素到最近的 0 的距离。

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

Given a matrix consists of 0 and 1, find the distance of the nearest 0 for each cell.

The distance between two adjacent cells is 1.

示例 1:

输入:

0 0 0
0 1 0
0 0 0

输出:

0 0 0
0 1 0
0 0 0

示例 2:

输入:

0 0 0
0 1 0
1 1 1

输出:

0 0 0
0 1 0
1 2 1

注意:

  1. 给定矩阵的元素个数不超过 10000。
  2. 给定矩阵中至少有一个元素是 0。
  3. 矩阵中的元素只在四个方向上相邻: 上、下、左、右。

Note:

  1. The number of elements of the given matrix will not exceed 10,000.
  2. There are at least one 0 in the given matrix.
  3. The cells are adjacent in only four directions: up, down, left and right.

解题思路:

​ 关键字:最近、距离。那肯定是广度优先搜索。类似之前的文章 岛屿数量: https://mp.weixin.qq.com/s/BrlMzXTtZWdB7hRfCKNMoQ

将这个问题转化成图,那就是求每个节点 1 到节点 0 最短的路径是多少。从某个节点开始,上下左右向外扩展,每次扩展一圈距离累加1,如:

输入:
1 1 1
0 1 0
0 0 0

转化成图(Graph),每种颜色代表一个层级:

这就变成了求某个节点到某个节点的深度了。

所以这道题有两种思路:

  • 以节点1为根节点,求该节点到节点0之间的深度
  • 以节点0为根节点,遇到最近的节点1路径计为1,再次以记录为1的节点为根节点继续向内遍历,遇到原节点1再次累加1并得到路径2,以此类推。。。

两种方法各有优劣,

以0节点为根节点解题,要么开辟一个新的二维数组以记录路径,要么先遍历一遍将所有的节点1的值改为不可能和路径大小重复的值。

以1节点为根节点,那么就要做一些多余的重复遍历。

以0为根节点:

逻辑顺序:

以输入下列二维数组为例:

1 1 1
0 1 1
0 0 1

先把原节点值为1 的节点改为M (路径值不可能达到的值,该题中大于10000即可)

先侵染0节点附近的M节点,0节点加1之后得到1节点

再侵染1节点附近的M节点,1节点加1之后得到2节点

......

Java:

class Solution {

    public int[][] updateMatrix(int[][] matrix) {
int row = matrix.length, column = matrix[0].length;
int[][] neighbors = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};//邻居节点的索引偏移量
Queue<int[]> queue = new LinkedList<>();//队列
for (int i = 0; i < row; i++) {
for (int j = 0; j < column; j++) {
if (matrix[i][j] == 0) queue.offer(new int[]{i, j});
else matrix[i][j] = Integer.MAX_VALUE;//节点值为1的节点改为一个路径不可能达到的值
}
}
while (!queue.isEmpty()) {
int[] tmp = queue.poll();
for (int i = 0; i < 4; i++) {
//得到邻居节点索引
int x = tmp[0] + neighbors[i][0];
int y = tmp[1] + neighbors[i][1];
if (x >= 0 && x < row && y >= 0 && y < column && matrix[tmp[0]][tmp[1]] < matrix[x][y]) {
matrix[x][y] = matrix[tmp[0]][tmp[1]] + 1;//该节点的值得到邻居节点的路径值+1
queue.offer(new int[]{x, y});
}
}
}
return matrix;
}
}

Python3:

class Solution:
def updateMatrix(self, matrix: List[List[int]]) -> List[List[int]]:
row, column = len(matrix), len(matrix[0])
nerghbors = [(0, 1), (0, -1), (1, 0), (-1, 0)]
queue = collections.deque()
for i in range(row):
for j in range(column):
if matrix[i][j] == 0:
queue.append((i, j))
else:
matrix[i][j] = 10001 while queue:
x, y = queue.popleft()
for i, j in nerghbors:
xx = i + x
yy = j + y
if 0 <= xx < row and 0 <= yy < column and matrix[x][y] < matrix[xx][yy]:
matrix[xx][yy] = matrix[x][y] + 1
queue.append((xx, yy)) return matrix

以1为根节点:

Java:

class Solution {
public int[][] updateMatrix(int[][] matrix) {
int row = matrix.length, column = matrix[0].length;
for (int i = 0; i < row; i++)
for (int j = 0; j < column; j++)
if (matrix[i][j] == 1) matrix[i][j] = bfs(matrix, i, j, row, column);
return matrix;
} private int bfs(int[][] matrix, int i, int j, int row, int column) {
int count = 0;
Queue<Integer> queue = new LinkedList<>();
Set<int[]> set = new HashSet<>();
queue.add(i * column + j);//记录索引的另一种方法
while (!queue.isEmpty()) {
int size = queue.size();
count += 1;
for (int k = 0; k < size; k++) {
int tmp = queue.poll();
int x = tmp / column, y = tmp % column;//得到索引坐标
//处理上下左右四个邻居节点,遇到0节点直接返回count路径值
if (x + 1 < row && !set.contains((x + 1) * column + y)) {
if (matrix[x + 1][y] != 0) queue.add((x + 1) * column + y);
else return count;
}
if (x - 1 >= 0 && !set.contains((x - 1) * column + y)) {
if (matrix[x - 1][y] != 0) queue.add((x - 1) * column + y);
else return count;
}
if (y + 1 < column && !set.contains(x * column + y + 1)) {
if (matrix[x][y + 1] != 0) queue.add(x * column + y + 1);
else return count;
}
if (y - 1 >= 0 && !set.contains(x * column + y - 1)) {
if (matrix[x][y - 1] != 0) queue.add(x * column + y - 1);
else return count;
}
}
}
return count;
}
}

Python3:

class Solution:
def updateMatrix(self, matrix: List[List[int]]) -> List[List[int]]:
row, column = len(matrix), len(matrix[0])
for i in range(row):
for j in range(column):
if matrix[i][j] == 1:
matrix[i][j] = self.bfs(i, j, matrix, row, column) return matrix def bfs(self, i: int, j: int, matrix: List[List[int]], row: int, column: int) -> int:
queue = collections.deque()
count = 0
nodeset = set()
queue.append((i, j))
while queue:
size = len(queue)
count += 1
for i in range(size):
x, y = queue.popleft()
if x + 1 < row and (x + 1, y) not in nodeset:
if matrix[x + 1][y] != 0:
queue.append((x + 1, y))
else:
return count
if x - 1 >= 0 and (x - 1, y) not in nodeset:
if matrix[x - 1][y] != 0:
queue.append((x - 1, y))
else:
return count
if y + 1 < column and (x, y + 1) not in nodeset:
if matrix[x][y + 1] != 0:
queue.append((x, y + 1))
else:
return count
if y - 1 >= 0 and (x, y - 1) not in nodeset:
if matrix[x][y - 1] != 0:
queue.append((x, y - 1))
else:
return count
return count

欢迎关注微.信公.众号:爱写Bug

Leetcode 542:01 矩阵 01的更多相关文章

  1. [Swift]LeetCode542. 01 矩阵 | 01 Matrix

    Given a matrix consists of 0 and 1, find the distance of the nearest 0 for each cell. The distance b ...

  2. Java实现 LeetCode 542 01 矩阵(暴力大法,正反便利)

    542. 01 矩阵 给定一个由 0 和 1 组成的矩阵,找出每个元素到最近的 0 的距离. 两个相邻元素间的距离为 1 . 示例 1: 输入: 0 0 0 0 1 0 0 0 0 输出: 0 0 0 ...

  3. Leetcode 542.01矩阵

    01矩阵 给定一个由 0 和 1 组成的矩阵,找出每个元素到最近的 0 的距离. 两个相邻元素间的距离为 1 . 示例 1: 输入: 0 0 0 0 1 0 0 0 0 输出: 0 0 0 0 1 0 ...

  4. [EOJ Monthly 2018.10][C. 痛苦的 01 矩阵]

    题目链接:C. 痛苦的 01 矩阵 题目大意:原题说的很清楚了,不需要简化_(:з」∠)_ 题解:设\(r_i\)为第\(i\)行中0的个数,\(c_j\)为第\(j\)列中0的个数,\(f_{i,j ...

  5. LeetCode初级算法--数组01:只出现一次的数字

    LeetCode初级算法--数组01:只出现一次的数字 搜索微信公众号:'AI-ming3526'或者'计算机视觉这件小事' 获取更多算法.机器学习干货 csdn:https://blog.csdn. ...

  6. LeetCode初级算法--字符串01:反转字符串

    LeetCode初级算法--字符串01:反转字符串 搜索微信公众号:'AI-ming3526'或者'计算机视觉这件小事' 获取更多算法.机器学习干货 csdn:https://blog.csdn.ne ...

  7. LeetCode初级算法--链表01:反转链表

    LeetCode初级算法--链表01:反转链表 搜索微信公众号:'AI-ming3526'或者'计算机视觉这件小事' 获取更多算法.机器学习干货 csdn:https://blog.csdn.net/ ...

  8. LeetCode初级算法--树01:二叉树的最大深度

    LeetCode初级算法--树01:二叉树的最大深度 搜索微信公众号:'AI-ming3526'或者'计算机视觉这件小事' 获取更多算法.机器学习干货 csdn:https://blog.csdn.n ...

  9. LeetCode初级算法--动态规划01:爬楼梯

    LeetCode初级算法--动态规划01:爬楼梯 搜索微信公众号:'AI-ming3526'或者'计算机视觉这件小事' 获取更多算法.机器学习干货 csdn:https://blog.csdn.net ...

随机推荐

  1. pytest框架之allure报告生成

    一.关于安装 allure是跟pytest一起集成使用的,所以需要同时安装pytest以及allure-pytest插件: pip install pytest pip install allure- ...

  2. POJ 1724 (分层图最短路)

    ### POJ 1724 题目链接 ### 题目大意: 给你 N 个点 ,M 条有向路,走每条路需要花费 C 元,这段路的长度为 L . 给你 K 元,问你能否从 1 走到 N 点且花费不超过 K 元 ...

  3. 三、动态SQL

    动态SQL MyBatis的动态SQL是基于OGNL表达式的,它可以帮助我们方便的在SQL语句中实现某些逻辑. 动态SQL的元素 元素 作用 备注 if 判断语句 单条件分支判断 choose.whe ...

  4. 2019年9月Github上最热门的JavaScript开源项目

      2019年9月Github上最热门的JavaScript开源项目 前端开发 前端开发 微信号 qianduan1024 功能介绍 专注于Web前端技术文章分享,包含JavaScript.HTML5 ...

  5. 一个Web前端工程师或程序员的发展方向,未来困境及穷途末路

    如果你刚好是一个Web前端工程师,或者你将要从事web前端工作.你应该和我有同样的感慨,web前端技术到了自己的天花板,前端工作我能做多少年?3年或5年?自己的职业规划应该怎么样?收入为什么没有增长? ...

  6. docker-mysql-使用docker运行mysql8

    1, 下载镜像, 我用的是8 docker pull mysql: 2, 启动镜像 docker run \ --name mysql8 \ -p : \ -v /Users/wenbronk/Con ...

  7. Rust开发环境搭建

    1.Rust概述 按照百度百科的说法,Rust是一门系统编程语言 ,专注于安全 ,尤其是并发安全,支持函数式和命令式以及泛型等编程范式的多范式语言.Rust在语法上和C++类似 ,但是设计者想要在保证 ...

  8. C# - WinFrm应用程序MessageBox自动关闭小实验

    概述 在程序中MessageBox弹出的对话框,用于向用户展示消息,这是一个模式窗口,可阻止应用程序中的其他操作,直到用户将其关闭.但是有时候在自动化程序中,如果弹出对话框,程序将会中断,等待人工的干 ...

  9. Python线程与进程 I/O多路复用

    SSHClient Paramiko模块 远程执行命令 #用户名密码方式: import paramiko ssh = paramiko.SSHClient() ssh.set_missing_hos ...

  10. django4-模板进阶

    1.模板系统的语法 引用变量数据: {{  }} 标签逻辑操作:{%...%} 2.变量 变量名由字符数字下划线组成 ,可以执行由视图函数传过来的对象的方法和属性 ,但是视图函数中如果使用 ' . ' ...