岛屿的最大面积

标签: 深度优先搜索 广度优先搜索 并查集 数组 矩阵

难度: Medium

给定一个由 01 组成的非空二维数组 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

注意:本题与主站 695 题相同: https://leetcode-cn.com/problems/max-area-of-island/

Submission

运行时间: 40 ms

内存: 16.7 MB

class Solution:
    def maxAreaOfIsland(self, grid: List[List[int]]) -> int:
        def dfs(i, j):
            if i<0 or i>=m or j<0 or j>=n or grid[i][j]==0:
                return 0
            area = grid[i][j]
            grid[i][j] = 0  
            #上下左右
            area += dfs(i-1, j)
            area += dfs(i+1, j)
            area += dfs(i, j-1)
            area += dfs(i, j+1)

            return area

        ans = 0
        m, n = len(grid), len(grid[0])
        for i in range(m):
            for j in range(n):
                if grid[i][j] > 0:
                    area = dfs(i, j)
                    # print(area)
                    ans = max(ans, area)
        return ans

Explain

该题解采用深度优先搜索(DFS)算法来解决岛屿的最大面积问题。从二维数组的每一个元素开始,如果当前元素是1(土地),则从该点出发使用DFS搜索所有连通的1,并在搜索过程中将遍历过的1设置为0以防重复计数。每次DFS会返回当前岛屿的面积,并与之前记录的最大面积进行比较,不断更新最大面积。这样,可以确保每个岛屿只被计算一次面积。

时间复杂度: O(m*n)

空间复杂度: O(m*n)

class Solution:
    def maxAreaOfIsland(self, grid: List[List[int]]) -> int:
        def dfs(i, j):
            # 边界检查以及当前位置是否为土地
            if i<0 or i>=m or j<0 or j>=n or grid[i][j]==0:
                return 0
            area = 1  # 当前土地面积计为1
            grid[i][j] = 0  # 访问过的土地标记为0
            # 对当前土地的上下左右进行DFS搜索
            area += dfs(i-1, j)
            area += dfs(i+1, j)
            area += dfs(i, j-1)
            area += dfs(i, j+1)
            return area

        ans = 0
        m, n = len(grid), len(grid[0])
        for i in range(m):
            for j in range(n):
                if grid[i][j] > 0:
                    area = dfs(i, j)
                    ans = max(ans, area)  # 更新最大岛屿面积
        return ans

Explore

在DFS函数中,在进行上下左右的递归搜索之前将当前土地标记为0,是为了防止重复访问和计数。标记为0后,表示该土地已经被访问过,这样在后续的递归调用中,当遇到已标记为0的土地时,会直接返回0,不会再次计算其面积,从而避免重复计算。这种做法简化了逻辑,确保了每块土地只被计算一次,并且有效地防止了在递归过程中可能出现的无限循环。

在题解中,每个岛屿只被计算一次面积的保证是通过将访问过的1(土地)改为0(水)来实现的。这一操作在DFS函数中进行,具体在`grid[i][j] = 0`这一行代码中。这样,一旦某块土地被访问并参与到某个岛屿面积的计算中,它就被标记为0,使得后续的任何搜索不会再次将其计入另一个岛屿的面积,从而确保了每个岛屿的面积只被准确计算一次。

DFS递归调用栈在最坏情况下可能达到m*n的深度,通常发生在整个网格都是陆地的情况下,例如当网格形状为一个很长的蛇形或完全填充的情况。在这种配置下,每个土地都连续递归访问,直到访问完所有的土地。为了避免栈溢出,可以考虑使用迭代的深度优先搜索(使用显式栈)或广度优先搜索(BFS)代替递归实现的DFS。BFS使用队列来实现,因此不会受到调用栈大小的限制,更适合处理大规模数据。