LeetCode 每日一题:最短的桥

93 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第 15 天,点击查看活动详情

最短的桥

原题地址

给你一个大小为 n x n 的二元矩阵 grid ,其中 1 表示陆地,0 表示水域。

是由四面相连的 1 形成的一个最大组,即不会与非组内的任何其他 1 相连。grid恰好存在两座岛

你可以将任意数量的 0 变为 1 ,以使两座岛连接起来,变成 一座岛

返回必须翻转的 0 的最小数目。

示例 1:

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

示例 2:

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

示例 3:

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

提示:

  • n == grid.length == grid[i].length
  • 2 <= n <= 100
  • grid[i][j]01
  • grid 中恰有两个岛

思路分析

  1. 题目中要求两座岛屿合成一座岛屿,我们就要考虑如何将两个岛屿合并成一座岛屿;
  2. 先使用 DFS 找到其中一座岛屿,并且将岛屿里面的所有坐标都存入 res 中;
  3. 再使用 BFS 从 DFS 中找到的岛屿终的点去寻找最近的坐标为1即为陆地的点;
  4. 若最后找不到,返回 -1 即可。

AC 代码

/**
 * @param {number[][]} grid
 * @return {number}
 */
var shortestBridge = function(grid) {
    const r = grid.length
    const c = grid[0].length
    const directions = [
        [0, 1],
        [0, -1],
        [1, 0],
        [-1, 0],
    ]
    const res = []
    const dfs = (i, j) => {
        // 1代表陆地  岛是由四面相连的 1 形成的一个最大组
        if (i < 0 || i >= r || j < 0 || j >= c || grid[i][j] !== 1) return
        // 标记小岛2
        grid[i][j] = 2
        // 初始化 res(记录小岛2的坐标)
        res.push([i, j])
        for (let [x, y] of directions) {
            dfs(i + x, j + y)
        }
    }
    
    const bfs = () => {
        let count = 0
        while (res.length) {
            let len = res.length
            count++
            while (len--) {
                const [i, j] = res.shift()
                // 向四周遍历
                for (let [x, y] of directions) {
                    const newI = i + x
                    const newJ = j + y
                    if (newI >= 0 && newI < r && newJ >= 0 && newJ < c) {
                        // 找到小岛1,直接返回
                        // 找到空白,继续前进搜寻
                        if (grid[newI][newJ] === 1) {
                            return count - 1
                        } else if (grid[newI][newJ] === 0) {
                            // 先把它融入小岛1中避免重复访问到
                            grid[newI][newJ] = 2
                            res.push([newI, newJ])
                        }
                    }
                }
            }
        }
    };
    for (let i = 0; i < r; i++) {
        for (let j = 0; j < c; j++) {
            if (grid[i][j] === 1) {
                dfs(i, j)
                return bfs()
            }
        }
    }
    return -1
};

结果:

  • 执行结果: 通过
  • 执行用时:92 ms, 在所有 JavaScript 提交中击败了48.94%的用户
  • 内存消耗:47.2 MB, 在所有 JavaScript 提交中击败了81.92%的用户
  • 通过测试用例:97 / 97

END