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

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

相关推荐
爱喝水的鱼丶32 分钟前
SAP-ABAP:条件判断与循环控制语句(7篇)第七篇:性能优化:条件与循环代码的常见性能瓶颈与优化方案
学习·算法·性能优化·sap·abap
吃好睡好便好5 小时前
提取矩阵某一行或某一列元素
开发语言·人工智能·线性代数·算法·matlab·矩阵
小江的记录本8 小时前
【JVM虚拟机】垃圾回收GC:四种引用类型:强引用、软引用、弱引用、虚引用(附《思维导图》+《面试高频考点清单》)
java·jvm·spring boot·后端·python·spring·面试
圣保罗的大教堂8 小时前
leetcode 2540. 最小公共值 简单
leetcode
APIshop8 小时前
Python 获取 1688 商品采集 API 接口 | 工厂货源自动化对接商品信息 | 无需选品
运维·python·自动化
deepin_sir8 小时前
10 - 函数
开发语言·python
云泽8089 小时前
笔试算法 -位运算篇(二):从唯一字符到消失数字
c++·算法·位运算
charlee449 小时前
《GIS基础原理与技术实践》配套案例(Python版)
python·conda·numpy·gis·环境配置
枫叶林FYL9 小时前
项目十:事件溯源仓储管理系统(WMS)仿真实现
开发语言·python
ʚ希希ɞ ྀ9 小时前
不同路径|| -- dp
算法