每日一题 934. 最短的桥

95 阅读1分钟

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

934. 最短的桥

给你一个大小为 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] 为 0 或 1
  • grid 中恰有两个岛

解题思路

  • 深度优先搜索
    1. 取得两个岛占据的区域的边缘点
    2. 从一个岛的边缘区域蔓延,直到和另外一个岛相交
    3. 蔓延的时候用栈保存每次蔓延后的边缘点,如果边缘点在另外一个岛出现了,蔓延的次数就是最少的0的次数
/**
 * @param {number[][]} grid
 * @return {number}
 */
var shortestBridge = function(grid) {
    const isLand1 = new Set
    let stack = new Set
    const n = grid.length
    const visited = Array.from({length: n}, () => new Array(n).fill(false))
    const steps = [[0, 1], [0, -1], [1, 0], [-1,0] ]

    for (let i = 0; i < n; i++) {
        for (let j = 0; j < n; j++) {
            if (visited[i][j] || !grid[i][j]) continue
            if (!isLand1.size) {
                getLan(isLand1, i, j)
            } else {
                getLan(stack, i, j)
            }
        }
    }

    function getLan(set, i, j) {
        set.add(`${i}%${j}`)
        visited[i][j] = true
        let count = 0
        for (const [x, y] of steps) {
            const cx = i + x
            const cy = j + y
            if (cx < 0 || cx >= n || cy < 0 || cy >= n || visited[cx][cy] || !grid[cx][cy]) continue
            count++
            getLan(set, cx, cy)
        }
        if (count >= 4) {
            set.delete(`${i}%${j}`)
        }
    }


    let min = 0
    while(stack.size) {
        const newSet = new Set
        for (const str of stack) {
            const [x, y] = str.split('%')
            for (const [dx, dy] of steps) {
                const cx = x - 0 + dx
                const cy = y - 0 + dy
                if (isLand1.has(`${cx}%${cy}`)) return min
                if (cx < 0 || cx >= n || cy < 0 || cy >= n || grid[cx][cy]) continue
                newSet.add(`${cx}%${cy}`)
                grid[cx][cy] = 1
            }
        }
        stack = newSet
        min++
    }
    
    return min
};