持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第29天,点击查看活动详情
给你一个大小为 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].length2 <= n <= 100grid[i][j]为0或1grid中恰有两个岛
思路
本题可以使用广度优先搜索解题。先找到其中的一个岛,遍历出所有相邻的水域(0),然后再遍历这些相邻的水域,找到他们相邻的水域,只到找到另一个岛(1),遍历次数就是最短路径。为了防止重复遍历,我们可以把遍历过的岛和水域标记为-1。
解题
/**
* @param {number[][]} grid
* @return {number}
*/
var shortestBridge = function (grid) {
let n = grid.length;
let sides = [];
const steps = [
[1, 0],
[-1, 0],
[0, 1],
[0, -1],
];
const getIsland = (i, j, grid) => {
if (i >= 0 && i < n && j >= 0 && j < n) {
const val = grid[i][j];
grid[i][j] = -1;
if (val === 1) {
for (let k = 0; k < 4; k++) {
getIsland(i + steps[k][0], j + steps[k][1], grid) && island;
}
} else if (val === 0) {
sides.push([i, j]);
}
}
};
let state = false;
for (let i = 0; i < n; i++) {
for (let j = 0; j < n; j++) {
if (grid[i][j] === 1) {
getIsland(i, j, grid);
state = true;
break;
}
}
if (state) {
break;
}
}
let res = 1;
while (true) {
let arr = [];
for (let i = 0; i < sides.length; i++) {
for (let k = 0; k < 4; k++) {
const r = sides[i][0] + steps[k][0];
const c = sides[i][1] + steps[k][1];
if (r >= 0 && r < n && c >= 0 && c < n) {
if (grid[r][c] === 0) {
arr.push([r, c]);
grid[r][c] = -1;
} else if (grid[r][c] === 1) {
return res;
}
}
}
}
res++;
sides = arr;
}
};