leetcode 542. 01 矩阵
xxleyi opened this issue · comments
题:
给定一个由 0 和 1 组成的矩阵,找出每个元素到最近的 0 的距离。
两个相邻元素间的距离为 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
注意:
给定矩阵的元素个数不超过 10000。
给定矩阵中至少有一个元素是 0。
矩阵中的元素只在四个方向上相邻: 上、下、左、右。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/01-matrix
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解:
这个题目,能一眼看出需要使用 bfs。但如何处理多个 0 的情况呢?自己并没有处理,导致复杂度陡增。此处涉及到一个巧妙的概念:超级起点。在之前的概念里,bfs 中初始化队列时,只会入队一个起点,但其实存在一种更为普遍的情况,就是存在超级起点:多个具体起点构成抽象意义上的单一起点。
var updateMatrix = function(matrix) {
// initialize loop invariant realted variable:
// dist matrix filled with -1 (-1 means not seen)
let m = matrix.length, n = matrix[0].length
let dist = Array(m)
for (let i = 0; i < m; i++) dist[i] = Array(n).fill(-1)
// initialize queue and enqueue all zero positions with one helper loop
// to maintain loop invariant before the main loop(bfs)
let head = 0, tail = -1, queue = Array(m * n)
for (let i = 0; i < m; i++) {
for (let j = 0; j < n; j++) {
if (matrix[i][j] === 0) {
dist[i][j] = 0
// update tail to maintain loop invariant
queue[++tail] = [i, j]
}
}
}
// helper variable and function
const dir = [[-1, 0], [1, 0], [0, -1], [0, 1]]
const validIJ = (i, j) => i >= 0 && i < m && j >= 0 && j < n
// main loop(bfs)
while (queue[head] != null) {
// dequeue one item
let [i, j] = queue[head++]
for (let [di, dj] of dir) {
let [ni, nj] = [i + di, j + dj]
// try to enqueue all valid positions which are unseen
if (validIJ(ni, nj) && dist[ni][nj] === -1) {
// update dist
dist[ni][nj] = dist[i][j] + 1
// enqueue new item
queue[++tail] = [ni, nj]
}
}
}
// loop termination: dist will be our answer
return dist
}