[LeetCode] 934. Shortest Bridge
You are given an n x n
binary matrix grid
where 1
represents land and 0
represents water.
An island is a 4-directionally connected group of 1
's not connected to any other 1
's. There are exactly two islands in grid
.
You may change 0
's to 1
's to connect the two islands to form one island.
Return the smallest number of 0
's you must flip to connect the two islands.
Example 1:
Input: grid = [[0,1],[1,0]] Output: 1
Example 2:
Input: grid = [[0,1,0],[0,0,0],[0,0,1]] Output: 2
Example 3:
Input: 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]] Output: 1
Constraints:
n == grid.length == grid[i].length
2 <= n <= 100
grid[i][j]
is either0
or1
.- There are exactly two islands in
grid
.
最短的桥。
给你一个大小为 n x n 的二元矩阵 grid ,其中 1 表示陆地,0 表示水域。
岛 是由四面相连的 1 形成的一个最大组,即不会与非组内的任何其他 1 相连。grid 中 恰好存在两座岛 。
你可以将任意数量的 0 变为 1 ,以使两座岛连接起来,变成 一座岛 。
返回必须翻转的 0 的最小数目。
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/shortest-bridge
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
题目问的是最少需要翻转多少个 0 使得两个岛相连,其实就是在找两个岛之间的最短距离,所以思路是 BFS。
这道题没有什么奇怪的 case,首先需要解决的问题是需要把两个岛屿分清楚。我们先遍历矩阵,去找第一个岛,找的时候,
- 我们用一个额外的 visited 数组记录坐标是否访问过
- 将访问过的坐标加入 queue 中,以便之后的 BFS
- 将第一个岛屿涉及到的所有坐标的坐标值从 1 改成 0
只要摸到任何一个 1,就说明摸到了第一个岛。然后借着这个 1,找到第一个岛屿的所有坐标,并在 visited 数组中标记好。此时我们再用 BFS 的方式开始弹出之前存储的第一个岛屿的坐标,并且也以 BFS 的方式加入他所有没有被访问过的邻居坐标,我们判断的是如果他没有被访问过但是他的坐标值是 1,那说明是来自第二个岛的坐标。此时就可以返回距离 steps 了。
时间O(mn)
空间O(mn)
Java实现
1 class Solution { 2 public int shortestBridge(int[][] grid) { 3 int m = grid.length; 4 int n = grid[0].length; 5 int[][] visited = new int[m][n]; 6 boolean found = false; 7 int[][] dirs = new int[][] { { 1, 0 }, { -1, 0 }, { 0, 1 }, { 0, -1 } }; 8 Queue<int[]> queue = new LinkedList<>(); 9 for (int i = 0; i < m; i++) { 10 if (found) { 11 break; 12 } 13 for (int j = 0; j < n; j++) { 14 if (grid[i][j] == 1) { 15 // find the first island 16 dfs(grid, visited, i, j, queue); 17 found = true; 18 break; 19 } 20 } 21 } 22 23 int steps = 0; 24 while (!queue.isEmpty()) { 25 int size = queue.size(); 26 for (int i = 0; i < size; i++) { 27 int[] cur = queue.poll(); 28 for (int[] dir : dirs) { 29 int x = cur[0] + dir[0]; 30 int y = cur[1] + dir[1]; 31 if (x >= 0 && y >= 0 && x < m && y < n && visited[x][y] == 0) { 32 if (grid[x][y] == 1) { 33 return steps; 34 } 35 queue.offer(new int[] { x, y }); 36 visited[x][y] = 1; 37 } 38 } 39 } 40 steps++; 41 } 42 return -1; 43 } 44 45 private void dfs(int[][] grid, int[][] visited, int i, int j, Queue<int[]> queue) { 46 // 越界的跳过 47 // 坐标值为0的跳过 - 因为不是第一个岛屿的一部分 48 // 访问过的坐标也跳过 49 if (i < 0 || j < 0 || i >= grid.length || j >= grid[0].length || grid[i][j] == 0 || visited[i][j] == 1) { 50 return; 51 } 52 visited[i][j] = 1; 53 queue.offer(new int[] { i, j }); 54 dfs(grid, visited, i - 1, j, queue); 55 dfs(grid, visited, i + 1, j, queue); 56 dfs(grid, visited, i, j - 1, queue); 57 dfs(grid, visited, i, j + 1, queue); 58 } 59 }