在问 · 算法题解

934. 最短的桥

题目描述

输入一个 n x n 的矩阵 grid,1 代表陆地,0 代表水。

上下左右相邻的陆地连成一块,一块极大的连通陆地称为一座岛。grid 中正好有两座岛。

你可以把任意多个 0 改成 1。返回让两座岛连成一座岛最少需要改动多少个 0。

示例 1
输入:grid = [[0,1],[1,0]]
输出:1

解释:改动 (0,0) 或 (1,1) 中的一个即可相连。

示例 2
输入:grid = [[0,1,0],[0,0,0],[0,0,1]]
输出:2

解释:两座岛在对角,至少要填两格水才能连通。

示例 3
输入: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]]
输出:1

解释:中间的小岛与外圈只隔一格水,填一格即可。

数据范围

  • n == grid.length == grid[i].length
  • 2 <= n <= 100
  • grid[i][j] 只会是 0 或 1。
  • grid 中恰好有两座岛。

解题思路

先用 DFS 找出第一座岛,把它的格子全部标成 2,并全部放进 frontier 作为 BFS 的起点。然后做多源 BFS,一层一层向海里扩展:每扩展一层 steps 加 1,新到达的海洋格也标成 2。一旦扩展时碰到值为 1 的格子,就说明到达了第二座岛,当前的 steps 就是需要翻转的 0 的数目。

为什么正确

第 steps 轮开始时,frontier 中的格子与第一座岛的距离都是 steps(第一座岛自身的距离为 0),且它们都已标成 2。

复杂度分析

时间 O(n²):DFS 和 BFS 都只访问每个格子常数次。空间 O(n²)。

易错点

必须把第一座岛的所有格子同时作为起点(多源 BFS),而不是只从一个格子出发;并且碰到 1 时返回的是当前层数 steps,而不是 steps+1,因为第一座岛周围的第 0 层邻居还没被翻转。

参考代码

Python、Java、C++、Go、JavaScript、TypeScript 六种语言,逻辑一致。

class Solution:
    def shortestBridge(self, grid: List[List[int]]) -> int:
        n = len(grid)
        start = next((r, c) for r in range(n) for c in range(n) if grid[r][c] == 1)
        grid[start[0]][start[1]] = 2
        stack = [start]
        frontier = [start]
        while stack:
            x, y = stack.pop()
            for nx, ny in ((x + 1, y), (x - 1, y), (x, y + 1), (x, y - 1)):
                if 0 <= nx < n and 0 <= ny < n and grid[nx][ny] == 1:
                    grid[nx][ny] = 2
                    stack.append((nx, ny))
                    frontier.append((nx, ny))
        steps = 0
        while frontier:
            nxt = []
            for x, y in frontier:
                for nx, ny in ((x + 1, y), (x - 1, y), (x, y + 1), (x, y - 1)):
                    if 0 <= nx < n and 0 <= ny < n:
                        if grid[nx][ny] == 1:
                            return steps
                        if grid[nx][ny] == 0:
                            grid[nx][ny] = 2
                            nxt.append((nx, ny))
            frontier = nxt
            steps += 1
        return -1

载入编辑器,自己跑一遍 →

图论 专题的其他题目

查看 图论 全部题目 →