英文原文
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
中的任意一个位置时,搜索的层数就是答案。
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;
}
}
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% |
提交历史
提交时间 | 提交结果 | 执行时间 | 内存消耗 | 语言 |
---|