英文原文
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
.
中文题目
在给定的二维二进制数组 A
中,存在两座岛。(岛是由四面相连的 1
形成的一个最大组。)
现在,我们可以将 0
变为 1
,以使两座岛连接起来,变成一座岛。
返回必须翻转的 0
的最小数目。(可以保证答案至少是 1
。)
示例 1:
输入:A = [[0,1],[1,0]] 输出:1
示例 2:
输入:A = [[0,1,0],[0,0,0],[0,0,1]] 输出:2
示例 3:
输入:A = [[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
提示:
2 <= A.length == A[0].length <= 100
A[i][j] == 0
或A[i][j] == 1
通过代码
官方题解
方法一:搜索
分析
我们使用的方法非常直接:首先找到这两座岛,随后选择一座,将它不断向外延伸一圈,直到到达了另一座岛。
在寻找这两座岛时,我们使用深度优先搜索。在向外延伸时,我们使用广度优先搜索。
算法
我们通过对数组 A
中的 1
进行深度优先搜索,可以得到两座岛的位置集合,分别为 source
和 target
。随后我们从 source
中的所有位置开始进行广度优先搜索,当它们到达了 target
中的任意一个位置时,搜索的层数就是答案。
[sol1]class Solution { public int shortestBridge(int[][] A) { int R = A.length, C = A[0].length; int[][] colors = getComponents(A); Queue<Node> queue = new LinkedList(); Set<Integer> target = new HashSet(); for (int r = 0; r < R; ++r) for (int c = 0; c < C; ++c) { if (colors[r][c] == 1) { queue.add(new Node(r, c, 0)); } else if (colors[r][c] == 2) { target.add(r * C + c); } } while (!queue.isEmpty()) { Node node = queue.poll(); if (target.contains(node.r * C + node.c)) return node.depth - 1; for (int nei: neighbors(A, node.r, node.c)) { int nr = nei / C, nc = nei % C; if (colors[nr][nc] != 1) { queue.add(new Node(nr, nc, node.depth + 1)); colors[nr][nc] = 1; } } } throw null; } public int[][] getComponents(int[][] A) { int R = A.length, C = A[0].length; int[][] colors = new int[R][C]; int t = 0; for (int r0 = 0; r0 < R; ++r0) for (int c0 = 0; c0 < C; ++c0) if (colors[r0][c0] == 0 && A[r0][c0] == 1) { // Start dfs Stack<Integer> stack = new Stack(); stack.push(r0 * C + c0); colors[r0][c0] = ++t; while (!stack.isEmpty()) { int node = stack.pop(); int r = node / C, c = node % C; for (int nei: neighbors(A, r, c)) { int nr = nei / C, nc = nei % C; if (A[nr][nc] == 1 && colors[nr][nc] == 0) { colors[nr][nc] = t; stack.push(nr * C + nc); } } } } return colors; } public List<Integer> neighbors(int[][] A, int r, int c) { int R = A.length, C = A[0].length; List<Integer> ans = new ArrayList(); if (0 <= r-1) ans.add((r-1) * R + c); if (0 <= c-1) ans.add(r * R + (c-1)); if (r+1 < R) ans.add((r+1) * R + c); if (c+1 < C) ans.add(r * R + (c+1)); return ans; } } class Node { int r, c, depth; Node(int r, int c, int d) { this.r = r; this.c = c; depth = d; } }
[sol1]class Solution(object): def shortestBridge(self, A): R, C = len(A), len(A[0]) def neighbors(r, c): for nr, nc in ((r-1,c),(r,c-1),(r+1,c),(r,c+1)): if 0 <= nr < R and 0 <= nc < C: yield nr, nc def get_components(): done = set() components = [] for r, row in enumerate(A): for c, val in enumerate(row): if val and (r, c) not in done: # Start dfs stack = [(r, c)] seen = {(r, c)} while stack: node = stack.pop() for nei in neighbors(*node): if A[nei[0]][nei[1]] and nei not in seen: stack.append(nei) seen.add(nei) done |= seen components.append(seen) return components source, target = get_components() print source, target queue = collections.deque([(node, 0) for node in source]) done = set(source) while queue: node, d = queue.popleft() if node in target: return d-1 for nei in neighbors(*node): if nei not in done: queue.append((nei, d+1)) done.add(nei)
复杂度分析
时间复杂度:$O(MN)$,其中 $M$ 和 $N$ 分别是数组
A
的行数和列数。空间复杂度:$O(MN)$。
统计信息
通过次数 | 提交次数 | AC比率 |
---|---|---|
25483 | 54067 | 47.1% |
提交历史
提交时间 | 提交结果 | 执行时间 | 内存消耗 | 语言 |
---|