[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 either 0 or 1.
  • 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 }

 

LeetCode 题目总结

posted @ 2020-11-12 01:22  CNoodle  阅读(223)  评论(0编辑  收藏  举报