LeetCode 算法入门 — 01 矩阵

518 阅读2分钟

Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情

01 矩阵

原题地址

给定一个由 01 组成的矩阵 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]]

思路分析

  1. 本题使用动态规划的方法来解决;
  2. 定义一个结果数组,因为寻找的是最短路径,因此给数组中的初值赋一个特别大的值 Number.MAX_SAFE_INTEGER / 2
  3. 第一次循环,寻找为0的元素 (i, j) ,它们的距离为 0
  4. 第二次循环,水平向左移动 和 竖直向上移动,寻找对应 (i, j) 的最小距离;
  5. 第三次循环,水平向左移动 和 竖直向下移动,寻找对应 (i, j) 的最小距离;
  6. 第四次循环,水平向右移动 和 竖直向上移动,寻找对应 (i, j) 的最小距离;
  7. 第五次循环,水平向右移动 和 竖直向下移动,寻找对应 (i, j) 的最小距离;
  8. 五次循环遍历完成后,得到最后的结果。

AC 代码

/**
 * @param {number[][]} mat
 * @return {number[][]}
 */
var updateMatrix = function(mat) {
    let m = mat.length
    let n = mat[0].length
    let result = []
    for (let i = 0; i < m; ++i) {
        result[i] = new Array(n).fill(Number.MAX_SAFE_INTEGER / 2)
    }
    for (let i = 0; i < m; i++) {
        for (let j = 0; j < n; j++) {
            if (mat[i][j] == 0) {
                result[i][j] = 0
            }
        }
    }
    // 水平向左移动和竖直向上移动
    for (let i = 0; i < m; i++) {
        for (let j = 0; j < n; j++) {
            if (i - 1 >= 0) {
                result[i][j] = Math.min(result[i][j], result[i - 1][j] + 1)
            }
            if (j - 1 >= 0) {
                result[i][j] = Math.min(result[i][j], result[i][j - 1] + 1)
            }
        }
    }
    // 水平向左移动和竖直向下移动
    for (let i = m - 1; i >= 0; i--) {
        for (let j = 0; j < n; j++) {
            if (i + 1 < m) {
                result[i][j] = Math.min(result[i][j], result[i + 1][j] + 1)
            }
            if (j - 1 >= 0) {
                result[i][j] = Math.min(result[i][j], result[i][j - 1] + 1)
            }
        }
    }
    // 水平向右移动和竖直向上移动
    for (let i = 0; i < m; i++) {
        for (let j = n - 1; j >= 0; j--) {
            if (i - 1 >= 0) {
                result[i][j] = Math.min(result[i][j], result[i - 1][j] + 1)
            }
            if (j + 1 < n) {
                result[i][j] = Math.min(result[i][j], result[i][j + 1] + 1)
            }
        }
    }
    // 水平向右移动和竖直向下移动
    for (let i = m - 1; i >= 0; i--) {
        for (let j = n - 1; j >= 0; j--) {
            if (i + 1 < m) {
                result[i][j] = Math.min(result[i][j], result[i + 1][j] + 1)
            }
            if (j + 1 < n) {
                result[i][j] = Math.min(result[i][j], result[i][j + 1] + 1)
            }
        }
    }
    return result
};

结果:

  • 执行结果: 通过
  • 执行用时:120 ms, 在所有 JavaScript 提交中击败了96.60%的用户
  • 内存消耗:49 MB, 在所有 JavaScript 提交中击败了64.84%的用户
  • 通过测试用例:50 / 50

END