加载中...
934-最短的桥(Shortest Bridge)
发表于:2021-12-03 | 分类: 中等
字数统计: 335 | 阅读时长: 1分钟 | 阅读量:

原文链接: https://leetcode-cn.com/problems/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.

中文题目

在给定的二维二进制数组 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] == 0A[i][j] == 1

通过代码

官方题解

方法一:搜索

分析

我们使用的方法非常直接:首先找到这两座岛,随后选择一座,将它不断向外延伸一圈,直到到达了另一座岛。

在寻找这两座岛时,我们使用深度优先搜索。在向外延伸时,我们使用广度优先搜索。

算法

我们通过对数组 A 中的 1 进行深度优先搜索,可以得到两座岛的位置集合,分别为 sourcetarget。随后我们从 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%

提交历史

提交时间 提交结果 执行时间 内存消耗 语言
上一篇:
933-最近的请求次数(Number of Recent Calls)
下一篇:
935-骑士拨号器(Knight Dialer)
本文目录
本文目录