Offer 驾到,掘友接招!我正在参与2022春招系列活动-刷题打卡任务,点击查看活动详情。
1、题目描述
给定一个由 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 <= 104
1 <= m * n <= 104
mat[i][j] is either 0 or 1.
mat 中至少有一个 0
2、思路分析
题目要求我们计算矩阵中每一个数字距离0的最近距离,只是一种很常见的问题,我们可以从以下几个方法考虑入手:
(1)暴力搜索
我们可以遍历这个矩阵,遇到1的时候就从该位置进行发散式搜索,找到距离最近的0,这是最直接的做法,但是其复杂度太高了,我们可以pass掉这个做法。
(2)深度优先搜索
我们可以从左上角开始进行深搜,遇到0就将当前所需最小步数置为0,否则则累加1并更新当前位置的最小步骤数值,遍历完后即可获得答案。深搜是一种有效的做法,但我们需要注意剪枝操作,否则其复杂度还是很高。
(3)广度优先搜索
这次我使用的是广度优先搜索,我们需要的是计算与0的距离,所以我们可以反过来思考,计算从0的位置出发,到每一个位置所需的步数,如下图所示:
主要步骤如下:
- 初始化步数矩阵,并将矩阵中为0的坐标入队
for(let i = 0; i < res.length; i++){
res[i] = new Array(mat[0].length).fill(Infinity);
for(let j = 0; j < mat[i].length; j++){
if(mat[i][j] === 0){
queue.push([i,j]);
res[i][j] = 0;
}
}
}
- 元素出队并将其四周的位置步数更新
while(queue.length > 0){
let q = queue.shift();
const dx = [1,0,-1,0],dy = [0,1,0,-1];
const x = q[0],y = q[1],val = res[x][y] + 1;
for(let i = 0; i < 4; i++){
const nx = dx[i] + x,ny = y + dy[i];
if(nx >= mat.length || nx < 0 || ny > mat[0].length || ny < 0) continue;
if(val < res[nx][ny]){
res[nx][ny] = val;
queue.push([nx,ny]);
}
}
}
- 将四周需要更新的位置入队
if(val < res[nx][ny]){
res[nx][ny] = val;
queue.push([nx,ny]);
}
AC代码
/**
* @param {number[][]} mat
* @return {number[][]}
*/
var updateMatrix = function(mat) {
let res = new Array(mat.length);
let queue = [];
for(let i = 0; i < res.length; i++){
res[i] = new Array(mat[0].length).fill(Infinity);
for(let j = 0; j < mat[i].length; j++){
if(mat[i][j] === 0){
queue.push([i,j]);
res[i][j] = 0;
}
}
}
while(queue.length > 0){
let q = queue.shift();
const dx = [1,0,-1,0],dy = [0,1,0,-1];
const x = q[0],y = q[1],val = res[x][y] + 1;
for(let i = 0; i < 4; i++){
const nx = dx[i] + x,ny = y + dy[i];
if(nx >= mat.length || nx < 0 || ny > mat[0].length || ny < 0) continue;
if(val < res[nx][ny]){
res[nx][ny] = val;
queue.push([nx,ny]);
}
}
}
return res;
};