0934. 最短的桥【中等】
1. 📝 题目描述
给你一个大小为 n x n 的二元矩阵 grid,其中 1 表示陆地,0 表示水域。
岛 是由四面相连的 1 形成的一个最大组,即不会与非组内的任何其他 1 相连。grid 中 恰好存在两座岛。
你可以将任意数量的 0 变为 1,以使两座岛连接起来,变成 一座岛。
返回必须翻转的 0 的最小数目。
示例 1:
txt
输入:grid = [[0,1],[1,0]]
输出:11
2
2
示例 2:
txt
输入:grid = [[0,1,0],[0,0,0],[0,0,1]]
输出:21
2
2
示例 3:
txt
输入: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]
]
输出:11
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
提示:
n == grid.length == grid[i].length2 <= n <= 100grid[i][j]为0或1grid中恰有两个岛
2. 🎯 s.1 - DFS + BFS
js
/**
* @param {number[][]} grid
* @return {number}
*/
var shortestBridge = function (grid) {
const n = grid.length
const dirs = [
[0, 1],
[0, -1],
[1, 0],
[-1, 0],
]
const queue = []
let found = false
// DFS 标记第一个岛为 2
const dfs = (i, j) => {
grid[i][j] = 2
queue.push([i, j])
for (const [di, dj] of dirs) {
const ni = i + di,
nj = j + dj
if (ni >= 0 && ni < n && nj >= 0 && nj < n && grid[ni][nj] === 1) {
dfs(ni, nj)
}
}
}
for (let i = 0; i < n && !found; i++) {
for (let j = 0; j < n && !found; j++) {
if (grid[i][j] === 1) {
dfs(i, j)
found = true
}
}
}
// BFS 找第二个岛
let step = 0
while (queue.length) {
const size = queue.length
for (let s = 0; s < size; s++) {
const [x, y] = queue.shift()
for (const [di, dj] of dirs) {
const nx = x + di,
ny = y + dj
if (nx >= 0 && nx < n && ny >= 0 && ny < n) {
if (grid[nx][ny] === 1) return step
if (grid[nx][ny] === 0) {
grid[nx][ny] = 2
queue.push([nx, ny])
}
}
}
}
step++
}
return -1
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
- 时间复杂度:
,其中 n 是矩阵的边长 - 空间复杂度:
,BFS 队列
算法思路:
- 用 DFS 标记第一个岛的所有格子为 2,并全部加入 BFS 队列
- 从队列做 BFS 向外扩展,每层扩展一步
- 当 BFS 遇到值为 1 的格子(第二个岛),返回当前步数即为最少翻转数