DFS岛屿问题部分汇总

LeetCode 上的岛屿问题通常是关于矩阵中岛屿的数量、面积、周长等问题。这些问题可以归纳为图的遍历问题,常见的解决方法包括深度优先搜索(DFS)和广度优先搜索(BFS)。 今天汇总一下我做过的一些DFS解决的岛屿问题。

463. 岛屿的周长 - 力扣(LeetCode)

给定一个 row x col 的二维网格地图 grid ,其中:grid[i][j] = 1 表示陆地, grid[i][j] = 0 表示水域。

网格中的格子 水平和垂直 方向相连(对角线方向不相连)。整个网格被水完全包围,但其中恰好有一个岛屿(或者说,一个或多个表示陆地的格子相连组成的岛屿)。

岛屿中没有"湖"("湖" 指水域在岛屿内部且不和岛屿周围的水相连)。格子是边长为 1 的正方形。网格为长方形,且宽度和高度均不超过 100 。计算这个岛屿的周长。

示例 1:

css 复制代码
输入: grid = [[0,1,0,0],[1,1,1,0],[0,1,0,0],[1,1,0,0]]
输出: 16
解释: 它的周长是上面图片中的 16 个黄色的边

示例 2:

lua 复制代码
输入: grid = [[1]]
输出: 4

示例 3:

lua 复制代码
输入: grid = [[1,0]]
输出: 4

提示:

  • row == grid.length
  • col == grid[i].length
  • 1 <= row, col <= 100
  • grid[i][j]01

代码

py 复制代码
class Solution:
    def islandPerimeter(self, grid):
        def dfs(grid, i, j):
            if not 0 <= i < len(grid) or not 0 <= j < len(grid[0]) or grid[i][j] == 0:
                return 1
            if grid[i][j] == -1:
                return 0
            grid[i][j] = -1
            t = dfs(grid, i - 1, j)
            b = dfs(grid, i + 1, j)
            l = dfs(grid, i, j - 1)
            r = dfs(grid, i, j + 1)
            return t + b + l + r

        count = 0
        for i in range(len(grid)):
            for j in range(len(grid[0])):
                if grid[i][j] == 1:
                    count += dfs(grid, i, j)

        return count

这个问题的解法是使用深度优先搜索(DFS)。

  1. dfs 函数是递归地计算从当前位置 (i, j) 出发的岛屿的周长。

    • 如果当前位置越界或者是水域(grid[i][j] == 0),返回 1(表示边界)。
    • 如果当前位置已经被访问过(grid[i][j] == -1),返回 0。
    • 将当前位置标记为已访问(grid[i][j] = -1)。
    • 递归地计算当前位置的上、下、左、右四个方向的周长,并将结果相加。
  2. 主函数 islandPerimeter 遍历整个网格,当发现岛屿(grid[i][j] == 1)时,调用 dfs 函数计算该岛屿的周长,并累加到 count 变量中。

  3. 最终返回累加的周长 count

这样,通过深度优先搜索递归计算每个岛屿的周长,最终得到整个岛屿的总周长。这题的关键点是在计算周长时,遇到岛屿的边界要返回1,同时需要标记已经访问过的岛屿,避免重复计算。

695. 岛屿的最大面积 - 力扣(LeetCode)

给你一个大小为 m x n 的二进制矩阵 grid

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

岛屿的面积是岛上值为 1 的单元格的数目。

计算并返回 grid 中最大的岛屿面积。如果没有岛屿,则返回面积为 0

示例 1:

css 复制代码
输入: 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
解释: 答案不应该是 11 ,因为岛屿只能包含水平或垂直这四个方向上的 1 。

示例 2:

lua 复制代码
输入: grid = [[0,0,0,0,0,0,0,0]]
输出: 0

提示:

  • m == grid.length
  • n == grid[i].length
  • 1 <= m, n <= 50
  • grid[i][j]01

代码

py 复制代码
class Solution:
    def maxAreaOfIsland(self, grid):
        m, n = len(grid), len(grid[0])

        def dfs(grid, i, j):
            if not 0 <= i < m or not 0 <= j < n or grid[i][j] == 0:
                return 0
            grid[i][j] = 0
            t = dfs(grid, i - 1, j)
            b = dfs(grid, i + 1, j)
            l = dfs(grid, i, j - 1)
            r = dfs(grid, i, j + 1)
            return t + b + l + r + 1

        maxS = 0
        for i in range(m):
            for j in range(n):
                if grid[i][j] == 1:
                    s = dfs(grid, i, j)
                    maxS = max(maxS,s)
        return maxS

这个解法同样是使用深度优先搜索(DFS)。以下是对代码的解析:

  1. dfs 函数负责计算从当前位置 (i, j) 出发的岛屿的面积。

    • 如果当前位置越界或者是水域(grid[i][j] == 0),返回 0。
    • 将当前位置标记为已访问(grid[i][j] = 0)。
    • 递归地计算当前位置的上、下、左、右四个方向的面积,并将结果相加。
    • 最终返回当前位置的面积 + 1,表示当前位置是陆地。
  2. 主函数 maxAreaOfIsland 遍历整个网格,当发现岛屿(grid[i][j] == 1)时,调用 dfs 函数计算该岛屿的面积,并与当前最大面积 maxS 比较,更新 maxS

  3. 最终返回最大面积 maxS

这个解法的核心思想是通过深度优先搜索递归地计算每个岛屿的面积,并在遍历过程中不断更新最大面积。同样地,已经访问过的陆地需要标记为水域,以避免重复计算。

200. 岛屿数量 - 力扣(LeetCode)

给你一个由 '1'(陆地)和 '0'(水)组成的的二维网格,请你计算网格中岛屿的数量。

岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。

此外,你可以假设该网格的四条边均被水包围。

示例 1:

css 复制代码
输入: grid = [  ["1","1","1","1","0"],
  ["1","1","0","1","0"],
  ["1","1","0","0","0"],
  ["0","0","0","0","0"]
]
输出: 1

示例 2:

css 复制代码
输入: grid = [  ["1","1","0","0","0"],
  ["1","1","0","0","0"],
  ["0","0","1","0","0"],
  ["0","0","0","1","1"]
]
输出: 3

提示:

  • m == grid.length
  • n == grid[i].length
  • 1 <= m, n <= 300
  • grid[i][j] 的值为 '0''1'

代码

py 复制代码
class Solution:
    def numIslands(self, grid) -> int:
        m, n = len(grid), len(grid[0])

        def dfs(grid,i, j):
            if not 0 <= i < m or not 0 <= j < n or grid[i][j] == '0':
                return
            grid[i][j] = '0'
            dfs(grid, i - 1, j)
            dfs(grid, i + 1, j)
            dfs(grid, i, j - 1)
            dfs(grid, i, j + 1)
        cnt = 0
        for i in range(m):
            for j in range(n):
                if grid[i][j] == '1':
                    dfs(grid,i,j)
                    cnt += 1
        return cnt

这个解法同样使用了深度优先搜索(DFS)。

  1. dfs 函数负责将当前位置 (i, j) 所在的岛屿标记为已访问,递归地将相邻的陆地标记为已访问。

    • 如果当前位置越界或者是水域(grid[i][j] == '0'),直接返回。
    • 将当前位置标记为已访问(grid[i][j] = '0')。
    • 递归地访问当前位置的上、下、左、右四个方向。
  2. 主函数 numIslands 遍历整个网格,当发现岛屿(grid[i][j] == '1')时,调用 dfs 函数将整个岛屿标记为已访问,并增加岛屿数量计数器 cnt

  3. 最终返回岛屿数量 cnt

这个解法的思路是遍历整个网格,每当发现未访问的岛屿时,通过深度优先搜索将整个岛屿标记为已访问。遍历完整个网格后,所有岛屿都被访问过,最终返回岛屿数量。

相关推荐
西柚与蓝莓1 小时前
【开源开放体系总结】
python
hsling松子4 小时前
使用PaddleHub智能生成,献上浓情国庆福
人工智能·算法·机器学习·语言模型·paddlepaddle
belldeep4 小时前
python:reportlab 将多个图片合并成一个PDF文件
python·pdf·reportlab
dengqingrui1235 小时前
【树形DP】AT_dp_p Independent Set 题解
c++·学习·算法·深度优先·图论·dp
C++忠实粉丝5 小时前
前缀和(8)_矩阵区域和
数据结构·c++·线性代数·算法·矩阵
ZZZ_O^O5 小时前
二分查找算法——寻找旋转排序数组中的最小值&点名
数据结构·c++·学习·算法·二叉树
CV-King6 小时前
opencv实战项目(三十):使用傅里叶变换进行图像边缘检测
人工智能·opencv·算法·计算机视觉
代码雕刻家6 小时前
数据结构-3.9.栈在递归中的应用
c语言·数据结构·算法
雨中rain6 小时前
算法 | 位运算(哈希思想)
算法
FreakStudio7 小时前
全网最适合入门的面向对象编程教程:56 Python字符串与序列化-正则表达式和re模块应用
python·单片机·嵌入式·面向对象·电子diy