题目难度: 中等

原题链接

今天继续更新 Leetcode 的剑指 Offer(专项突击版)系列, 大家在公众号 算法精选 里回复 剑指offer2 就能看到该系列当前连载的所有文章了, 记得关注哦~

题目描述

给定一个由 0 和 1 组成的非空二维数组 grid ,用来表示海洋岛屿地图。

一个 岛屿 是由一些相邻的 1 (代表土地) 构成的组合,这里的「相邻」要求两个 1 必须在水平或者竖直方向上相邻。你可以假设 grid 的四个边缘都被 0(代表水)包围着。

找到给定的二维数组中最大的岛屿面积。如果没有岛屿,则返回面积为 0 。

示例 1:

  • 输入: grid = [[0,0,1,0,0,0,0,1,0,0,0,0,0],[0,0,0,0,0,0,0,1,1,1,0,0,0],[0,1,1,0,1,0,0,0,0,0,0,0,0],[0,1,0,0,1,1,0,0,1,0,1,0,0],[0,1,0,0,1,1,0,0,1,1,1,0,0],[0,0,0,0,0,0,0,0,0,0,1,0,0],[0,0,0,0,0,0,0,1,1,1,0,0,0],[0,0,0,0,0,0,0,1,1,0,0,0,0]]
  • 输出: 6
  • 解释: 对于上面这个给定矩阵应返回 6。注意答案不应该是 11 ,因为岛屿只能包含水平或垂直的四个方向的 1 。

示例 2:

  • 输入: grid = [[0,0,0,0,0,0,0,0]]
  • 输出: 0

提示:

  • m == grid.length
  • n == grid[i].length
  • 1 <= m, n <= 50
  • grid[i][j] is either 0 or 1

题目思考

  1. 如何得到哪些土地相互连通?

解决方案

  • 分析题目, 不难发现这道题的核心在于求连通分量, 所以我们可以采用经典的 BFS 算法:
    • 遍历所有格子, 如果当前格子是尚未访问的土地, 则从它开始向上下左右四个方向扩散, 找相邻的土地
    • 然后将访问过的土地格子都标记为已访问, 直到这些点都处理完毕
    • 此时遍历的格子数目即为当前岛屿大小
  • 相比传统的 BFS, 我们这里可以做出一些改进, 从而做到不需要使用额外的 visit 集合来判断哪些点已经被遍历过
  • 具体做法是: 访问过某个土地格子后, 就将其值改为 0, 说白了就是将原有土地变成水, 这样就不会再次处理它
  • 最终结果就是所有岛屿大小的最大值
  • 下面的代码对必要步骤有详细的解释, 方便大家理解

复杂度

  • 时间复杂度 O(RC): R 和 C 是矩阵的行和列数, 每个格子只需要访问常数次 (判断或填充)
  • 空间复杂度 O(1): 只使用了常数空间的变量

代码

class Solution:
    def maxAreaOfIsland(self, grid: List[List[int]]) -> int:
        # BFS+原地更改
        rows, cols = len(grid), len(grid[0])
        res = 0
        for sr in range(rows):
            for sc in range(cols):
                if grid[sr][sc] == 1:
                    # 找到一个尚未遍历过的土地, 开始BFS
                    q = [(sr, sc)]
                    # 将原有土地变成水, 更改其值为0, 避免重复遍历
                    grid[sr][sc] = 0
                    for r, c in q:
                        for rr, cc in ((r + 1, c), (r - 1, c), (r, c + 1), (r, c - 1)):
                            # 判断4个方向的相邻格子
                            if 0 <= rr < rows and 0 <= cc < cols and grid[rr][cc] == 1:
                                # 当前相邻格子也是土地, 属于岛屿的一部分
                                q.append((rr, cc))
                                # 同样将其值改为0, 避免重复遍历
                                grid[rr][cc] = 0
                    # 最后队列q的长度即为当前岛屿大小, 取最大值作为最终结果
                    res = max(res, len(q))
        return res

大家可以在下面这些地方找到我~😊

我的 GitHub

我的 Leetcode

我的 CSDN

我的知乎专栏

我的头条号

我的牛客网博客

我的公众号: 算法精选, 欢迎大家扫码关注~😊

算法精选 - 微信扫一扫关注我