当前位置: 首页 > article >正文

代码随想录训练营 Day51打卡 图论part02 99. 岛屿数量 100. 岛屿的最大面积

代码随想录训练营 Day51打卡 图论part02

一、卡码99. 岛屿数量

题目描述
给定一个由 1(陆地)和 0(水)组成的矩阵,你需要计算岛屿的数量。岛屿由水平方向或垂直方向上相邻的陆地连接而成,并且四周都是水域。你可以假设矩阵外均被水包围。
输入描述
第一行包含两个整数 N, M,表示矩阵的行数和列数。
后续 N 行,每行包含 M 个数字,数字为 1 或者 0。
输出描述
输出一个整数,表示岛屿的数量。如果不存在岛屿,则输出 0。
输入示例
4 5
1 1 0 0 0
1 1 0 0 0
0 0 1 0 0
0 0 0 1 1
输出示例
3
提示信息

根据测试案例中所展示,岛屿数量共有 3 个,所以输出 3。

核心步骤:
深度优先搜索 (DFS):当找到一块未访问的陆地时,使用 DFS 遍历所有与它相邻的陆地,并标记为已访问。DFS 会递归地访问所有四个方向上的相邻陆地。
计数岛屿:每找到一个新的未访问的陆地,岛屿数加一,同时使用 DFS 标记所有相邻的陆地,防止重复计数。
边界检查:每次访问新的坐标时,需要确保坐标合法(不越界)且是未访问的陆地。

DFS

# 定义四个方向:上、右、下、左
direction = [[0, 1], [1, 0], [0, -1], [-1, 0]]  # 上右下左四个方向

def dfs(grid, visited, x, y):
    """
    对一块陆地进行深度优先遍历并标记
    :param grid: 二维网格,1 代表陆地,0 代表水
    :param visited: 记录哪些节点被访问过
    :param x: 当前节点的行索引
    :param y: 当前节点的列索引
    """
    for i, j in direction:
        next_x = x + i
        next_y = y + j
        # 判断坐标是否越界
        if next_x < 0 or next_x >= len(grid) or next_y < 0 or next_y >= len(grid[0]):
            continue  # 越界直接跳过
        # 如果是未访问的陆地,进行递归遍历
        if not visited[next_x][next_y] and grid[next_x][next_y] == 1:
            visited[next_x][next_y] = True  # 标记为已访问
            dfs(grid, visited, next_x, next_y)  # 递归调用,继续深度遍历

if __name__ == '__main__':
    # 输入网格的大小:n 表示行数,m 表示列数
    n, m = map(int, input().split())
    
    # 构建网格 (邻接矩阵表示法)
    grid = []
    for i in range(n):
        grid.append(list(map(int, input().split())))  # 每行输入网格

    # 初始化访问表,标记哪些节点已访问过
    visited = [[False] * m for _ in range(n)]
    
    # 岛屿计数结果
    res = 0
    # 遍历网格的每个点
    for i in range(n):
        for j in range(m):
            # 如果当前点是未访问的陆地
            if grid[i][j] == 1 and not visited[i][j]:
                res += 1  # 找到一个新的岛屿,岛屿数加 1
                visited[i][j] = True  # 标记为已访问
                dfs(grid, visited, i, j)  # 对该点进行深度优先搜索,标记相邻的陆地

    # 输出岛屿的数量
    print(res)

BFS 实现思路:

  1. 队列
    (Queue):使用队列来保存当前层需要访问的节点,每次从队列中取出一个节点,将其所有相邻的未访问陆地加入队列,直到所有与该节点相连的陆地都遍历完。
  2. 邻接矩阵表示:同样使用二维数组(邻接矩阵)表示网格,1 表示陆地,0 表示水。
  3. 计数岛屿:每次找到一个新的未访问陆地时,岛屿数量加 1,使用 BFS 来遍历整个岛屿,确保该岛屿上的所有陆地都被标记为已访问。

BFS

from collections import deque

# 定义四个方向:上、右、下、左
direction = [[0, 1], [1, 0], [0, -1], [-1, 0]]  # 上、右、下、左

def bfs(grid, visited, x, y):
    """
    使用 BFS 遍历和标记岛屿
    :param grid: 二维网格,1 代表陆地,0 代表水
    :param visited: 记录哪些节点被访问过
    :param x: 起点的行索引
    :param y: 起点的列索引
    """
    # 初始化一个队列,将起点加入队列并标记为已访问
    queue = deque()
    queue.append((x, y))
    visited[x][y] = True  # 标记起点已访问

    # 开始广度优先搜索
    while queue:
        cur_x, cur_y = queue.popleft()  # 从队列中取出当前节点
        
        # 遍历当前节点的四个相邻方向
        for i, j in direction:
            next_x = cur_x + i
            next_y = cur_y + j
            # 判断是否越界以及是否是未访问的陆地
            if 0 <= next_x < len(grid) and 0 <= next_y < len(grid[0]):
                if not visited[next_x][next_y] and grid[next_x][next_y] == 1:
                    # 如果是未访问的陆地,加入队列并标记为已访问
                    visited[next_x][next_y] = True
                    queue.append((next_x, next_y))

if __name__ == '__main__':
    # 输入网格的大小:n 表示行数,m 表示列数
    n, m = map(int, input().split())
    
    # 构建网格 (邻接矩阵表示法)
    grid = [list(map(int, input().split())) for _ in range(n)]

    # 初始化访问表,标记哪些节点已访问过
    visited = [[False] * m for _ in range(n)]
    
    # 岛屿计数结果
    res = 0
    # 遍历网格的每个点
    for i in range(n):
        for j in range(m):
            # 判断:如果当前节点是未访问的陆地
            if grid[i][j] == 1 and not visited[i][j]:
                res += 1  # 找到一个新的岛屿,岛屿数加 1
                bfs(grid, visited, i, j)  # 使用 BFS 搜索并标记该岛屿

    # 输出岛屿的数量
    print(res)

总结

  • BFS 通过使用队列逐层访问相邻节点,非常适合处理需要按层次逐步扩展的搜索问题。
  • DFS 适合更深层次的递归搜索,而 BFS 更注重广度、层次上的扩展。对于岛屿计数问题,BFS 和 DFS都可以高效解决,关键在于如何标记已访问的节点,防止重复计数。

题目链接
题目文章讲解

二、卡码100. 岛屿的最大面积

题目描述
给定一个由 1(陆地)和 0(水)组成的矩阵,计算岛屿的最大面积。岛屿面积的计算方式为组成岛屿的陆地的总数。岛屿由水平方向或垂直方向上相邻的陆地连接而成,并且四周都是水域。你可以假设矩阵外均被水包围。
输入描述
第一行包含两个整数 N, M,表示矩阵的行数和列数。后续 N 行,每行包含 M 个数字,数字为 1 或者 0,表示岛屿的单元格。
输出描述
输出一个整数,表示岛屿的最大面积。如果不存在岛屿,则输出 0。
输入示例
4 5
1 1 0 0 0
1 1 0 0 0
0 0 1 0 0
0 0 0 1 1
输出示例
4
提示信息

样例输入中,岛屿的最大面积为 4。

主要步骤:

  1. 深度优先搜索 (DFS):对于每块未访问的陆地(grid[i][j] == 1 且 visited[i][j] == False),使用DFS 遍历所有与它相连的陆地块,并统计连通区域的大小。DFS 递归遍历四个方向,确保所有相连的陆地都被访问。
  2. 计数连通陆地的面积:每次通过 DFS 遍历完一块连通的陆地块后,记录该区域的大小,并在所有遍历完成后输出最大的区域面积。
  3. 全局变量 count:在 DFS 中使用全局变量 count 来记录当前遍历到的连通陆地块的大小。每次发现一块新陆地时,count 从1 开始计数,DFS 过程中每找到一块相邻的陆地块,count 增加 1。

代码实现

# 定义四个方向:上、右、下、左
position = [[0, 1], [1, 0], [0, -1], [-1, 0]]
count = 0  # 全局变量,用于记录当前连通陆地的面积

def dfs(grid, visited, x, y):
    """
    深度优先搜索,遍历并标记一整块连通的陆地
    :param grid: 二维网格,1 代表陆地,0 代表水
    :param visited: 记录哪些节点被访问过
    :param x: 当前节点的行索引
    :param y: 当前节点的列索引
    """
    global count  # 使用全局变量 count 记录当前连通区域的面积
    for i, j in position:  # 遍历四个方向:上、右、下、左
        cur_x = x + i
        cur_y = y + j
        # 判断坐标是否越界
        if cur_x < 0 or cur_x >= len(grid) or cur_y < 0 or cur_y >= len(grid[0]):
            continue  # 如果越界,跳过该方向
        # 如果当前节点是未访问的陆地块,继续递归遍历
        if not visited[cur_x][cur_y] and grid[cur_x][cur_y] == 1:
            visited[cur_x][cur_y] = True  # 标记为已访问
            count += 1  # 当前连通陆地面积加 1
            dfs(grid, visited, cur_x, cur_y)  # 递归搜索相邻的陆地块

# 主函数,读取输入并处理
n, m = map(int, input().split())  # 输入网格的大小 n 行 m 列
# 构建网格,读取每行输入作为网格的一部分
grid = []
for i in range(n):
    grid.append(list(map(int, input().split())))  # 每行输入陆地/水域信息
# 初始化访问数组,记录哪些节点已访问过
visited = [[False] * m for _ in range(n)]

result = 0  # 记录所有连通陆地块中的最大面积
# 遍历整个网格
for i in range(n):
    for j in range(m):
        # 如果当前节点是未访问的陆地块,开始新的 DFS 遍历
        if grid[i][j] == 1 and not visited[i][j]:
            count = 1  # 初始化当前连通区域的面积为 1
            visited[i][j] = True  # 标记当前节点为已访问
            dfs(grid, visited, i, j)  # 使用 DFS 遍历相连的陆地块
            result = max(count, result)  # 更新最大的连通区域面积

# 输出结果,最大连通陆地面积
print(result)


题目链接
题目文章讲解


http://www.kler.cn/a/292352.html

相关文章:

  • 【route】route add命令详解
  • 掌握C#中的异步编程:async和await关键字详解
  • Python教程笔记(3)
  • 【NLP】医学搜索Query相关性判断【阿里云:天池比赛】
  • Java I/O(输入/输出)——针对实习面试
  • Unity教程(十八)战斗系统 攻击逻辑
  • 利用全核范数去噪技术优化彩色图像处理
  • llamafactory微调llama3.1
  • 2024 数学建模高教社杯 国赛(A题)| “板凳龙”舞龙队 | 建模秘籍文章代码思路大全
  • 本地 springboot 项目如何使用 https 进行访问
  • Java项目:141 springboot大学生智能消费记账系统的设计与实现
  • 拥抱分布式云:云基础设施的下个新时代
  • 目标检测-YOLOv1
  • IDEA运行Java程序提示“java: 警告: 源发行版 11 需要目标发行版 11”
  • java项目热部署
  • 蚂蚁SEO|AI养站程序是什么|蚂蚁蜘蛛池
  • 职场关系课:职场上的基本原则(安全原则、进步原则、收益原则、逃生舱原则)
  • 【Godot4.3】CanvasShape资源化改造
  • ChatGPT付费创作系统V3.0.6独立版 WEB+H5+小程序端 (新增AI全网搜索+文档解析+豆包AI通道)安装部署教程
  • 专访|“技术+市场”双轮驱动,积鼎科技如何打造国产CFD流体仿真软件标杆品牌?
  • WPS中JS宏使用说明(持续优化...)
  • Flutter中添加崩溃分析
  • 【云原生•容器】Docker架构剖析,它还是从前那个Docker吗?(上)
  • 记录Java秋招面经(网上找的)
  • 江协科技STM32学习- P11 中断系统,EXTI外部中断
  • Java项目:139 springboot基于SpringBoot的论坛系统设计与实现