代码随想录算法训练营第五十二天|101.孤岛的总面积 、102.沉没孤岛 、103.水流问题 、104.建造最大岛屿

news2024/9/24 11:27:03

101. 孤岛的总面积

DFS搜索:

  1. dfs 函数是一个递归函数,用于深度优先搜索(DFS)遍历网格中的陆地区域。它将访问过的陆地标记为0,并统计陆地的数量。

  2. 我们首先定义了四个方向的移动偏移量 dir

  3. global count 语句用于声明 count 为全局变量,以便在 dfs 函数中修改它。

  4. dfs 函数开始处,先进行条件判断,如果当前坐标越界或不是陆地(值为1),则直接返回。这是终止条件。

  5. 如果当前单元格是陆地,将其标记为已访问(设置为0),并增加 count

  6. 通过递归调用 dfs 函数,继续向四个方向搜索,直到所有连通的陆地都被访问。

  7. main 函数首先读取输入,初始化网格和全局计数器 count

  8. 然后,代码分别从网格的四边开始,向中间搜索,对每个找到的陆地区域执行 dfs,并将访问过的陆地标记为海水。

  9. 搜索完边缘后,重置 count 并继续搜索剩余的陆地区域,计算连通的陆地区域数量。

def dfs(grid, x, y):
    # 定义四个方向的移动偏移量
    dir = [[-1, 0], [0, -1], [1, 0], [0, 1]]
    global count  # 使用全局变量count来统计陆地空格数量
    if not (0 <= x < len(grid) and 0 <= y < len(grid[0]) and grid[x][y] == 1):
        return  # 先判断终止条件:坐标越界或不是陆地
    grid[x][y] = 0  # 标记访问过的陆地为0(海水)
    count += 1  # 增加陆地数量计数
    for dx, dy in dir:  # 向四个方向遍历
        nextx, nexty = x + dx, y + dy
        dfs(grid, nextx, nexty)  # 对新位置递归调用dfs函数

def main():
    global count  # 声明全局变量count
    count = 0
    n, m = map(int, input().split())
    grid = []
    for _ in range(n):
        grid.append(list(map(int, input().split())))

    # 从左侧边和右侧边向中间遍历
    for i in range(n):
        if grid[i][0] == 1: dfs(grid, i, 0)
        if grid[i][m - 1] == 1: dfs(grid, i, m - 1)
    # 从上边和下边向中间遍历
    for j in range(m):
        if grid[0][j] == 1: dfs(grid, 0, j)
        if grid[n - 1][j] == 1: dfs(grid, n - 1, j)

    # 重置count,重新计算剩余的陆地区域数量
    count = 0
    for i in range(n):
        for j in range(m):
            if grid[i][j] == 1:
                dfs(grid, i, j)  # 对每个未访问的陆地区域执行dfs
                count += 1  # 增加连通区域的计数

    print(count)  # 打印连通陆地区域的数量

if __name__ == "__main__":
    main()

BFS搜索:

from collections import deque

def bfs(grid, x, y):
    # 定义四个方向的移动偏移量
    dir = [[0, 1], [1, 0], [0, -1], [-1, 0]]
    global count  # 使用全局变量count来统计遍历的陆地数量
    queue = deque([(x, y)])  # 使用双端队列deque实现广度优先搜索
    grid[x][y] = 0  # 将起始点标记为已访问
    count += 1  # 起始点计入陆地数量
    while queue:
        curx, cury = queue.popleft()  # 从队列中取出当前点
        for dx, dy in dir:  # 遍历四个方向
            nextx, nexty = curx + dx, cury + dy
            # 检查新坐标是否在网格内
            if 0 <= nextx < len(grid) and 0 <= nexty < len(grid[0]):
                # 如果新坐标是未访问的陆地,则加入队列并标记
                if grid[nextx][nexty] == 1:
                    queue.append((nextx, nexty))
                    count += 1
                    grid[nextx][nexty] = 0  # 标记为已访问

def main():
    global count  # 声明全局变量count
    count = 0
    n, m = map(int, input().split())
    grid = [list(map(int, input().split())) for _ in range(n)]

    # 从网格的边缘向中间遍历
    for i in range(n):
        if grid[i][0] == 1: bfs(grid, i, 0)  # 左侧边
        if grid[i][m - 1] == 1: bfs(grid, i, m - 1)  # 右侧边
    for j in range(m):
        if grid[0][j] == 1: bfs(grid, 0, j)  # 上边
        if grid[n - 1][j] == 1: bfs(grid, n - 1, j)  # 下边

    # 重置count,重新计算网格内部的陆地数量
    count = 0
    for i in range(n):
        for j in range(m):
            if grid[i][j] == 1:
                bfs(grid, i, j)  # 遍历剩余的陆地
                count += 1  # 增加连通区域的计数

    print(count)  # 打印连通陆地区域的数量

if __name__ == "__main__":
    main()

102. 沉没孤岛

步骤一:深搜或者广搜将地图周边的 1 (陆地)全部改成 2 (特殊标记)

步骤二:将水域中间 1 (陆地)全部改成 水域(0)

步骤三:将之前标记的 2 改为 1 (陆地)

def dfs(grid, x, y):
    # 定义四个方向的移动偏移量
    dir = [[-1, 0], [0, -1], [1, 0], [0, 1]]
    grid[x][y] = 2  # 将当前访问的陆地标记为2
    for dx, dy in dir:  # 向四个方向遍历
        nextx, nexty = x + dx, y + dy
        # 检查新坐标是否越界
        if nextx < 0 or nextx >= len(grid) or nexty < 0 or nexty >= len(grid[0]):
            continue
        # 如果新坐标是未访问的陆地(值为1)且没有被标记过(不是2)
        if grid[nextx][nexty] == 1:
            dfs(grid, nextx, nexty)  # 递归遍历

def main():
    n, m = map(int, input().split())
    grid = [list(map(int, input().split())) for _ in range(n)]

    # 步骤一:从网格边缘向中间遍历
    for i in range(n):
        if grid[i][0] == 1: dfs(grid, i, 0)  # 左侧边
        if grid[i][m - 1] == 1: dfs(grid, i, m - 1)  # 右侧边
    for j in range(m):
        if grid[0][j] == 1: dfs(grid, 0, j)  # 上边
        if grid[n - 1][j] == 1: dfs(grid, n - 1, j)  # 下边

    # 步骤二、步骤三:将边缘遍历标记过的陆地(2)还原为陆地(1)
    # 并将未访问的陆地(1)标记为未访问(0)
    for i in range(n):
        for j in range(m):
            if grid[i][j] == 1:
                grid[i][j] = 0
            elif grid[i][j] == 2:
                grid[i][j] = 1

    # 打印最终的网格状态
    for row in grid:
        print(" ".join(map(str, row)))

if __name__ == "__main__":
    main()

103. 水流问题

反向思维:从第一组边界上的节点 逆流而上,将遍历过的节点都标记上。

同样从第二组边界的边上节点 逆流而上,将遍历过的节点也标记上。

然后两方都标记过的节点就是既可以流太平洋也可以流大西洋的节点

def dfs(grid, visited, x, y):
    # 定义四个方向的移动偏移量
    dir = [[-1, 0], [0, -1], [1, 0], [0, 1]]
    if visited[x][y]:
        return

    visited[x][y] = True

    for dx, dy in dir:
        nextx, nexty = x + dx, y + dy
        # 检查新坐标是否越界
        if not (0 <= nextx < len(grid)) or not (0 <= nexty < len(grid[0])):
            continue
        # 注意:这里是从低向高遍历
        if grid[x][y] > grid[nextx][nexty]:
            continue
        dfs(grid, visited, nextx, nexty)

def main():
    global n, m
    n, m = map(int, input().split())
    grid = [list(map(int, input().split())) for _ in range(n)]

    # 初始化两个边界访问矩阵
    firstBorder = [[False] * m for _ in range(n)]
    secondBorder = [[False] * m for _ in range(n)]

    # 从最上和最下行的节点出发,向高处遍历
    for i in range(n):
        dfs(grid, firstBorder, i, 0)  # 遍历最左列
        dfs(grid, secondBorder, i, m - 1)  # 遍历最右列

    # 从最左和最右列的节点出发,向高处遍历
    for j in range(m):
        dfs(grid, firstBorder, 0, j)  # 遍历最上行
        dfs(grid, secondBorder, n - 1, j)  # 遍历最下行

    # 找出两个边界都能访问到的节点
    for i in range(n):
        for j in range(m):
            if firstBorder[i][j] and secondBorder[i][j]:
                print(i, j)

if __name__ == "__main__":
    main()

104. 建造最大岛屿

第一步:一次遍历地图,得出各个岛屿的面积,并做编号记录。可以使用map记录,key为岛屿编号,value为岛屿面积

第二步:再遍历地图,遍历0的方格(因为要将0变成1),并统计该1(由0变成的1)周边岛屿面积,将其相邻面积相加在一起,遍历所有 0 之后,就可以得出 选一个0变成1 之后的最大面积。

def dfs(grid, visited, x, y, mark):
    # 定义四个方向的移动偏移量
    dir = [[0, 1], [1, 0], [0, -1], [-1, 0]]
    if visited[x][y] or grid[x][y] == 0:  # 终止条件:访问过的节点 或者 遇到海水
        return
    visited[x][y] = True  # 标记访问过
    grid[x][y] = mark  # 给陆地标记新标签
    for dx, dy in dir:  # 向四个方向遍历
        nextx, nexty = x + dx, y + dy
        if 0 <= nextx < len(grid) and 0 <= nexty < len(grid[0]):  # 检查是否越界
            dfs(grid, visited, nextx, nexty, mark)

def main():
    global n, m, count
    n, m = map(int, input().split())
    grid = [list(map(int, input().split())) for _ in range(n)]
    visited = [[False] * m for _ in range(n)]  # 标记访问过的点
    gridNum = {}  # 记录每个岛屿的面积
    mark = 2  # 记录每个岛屿的编号
    isAllGrid = True  # 标记是否整个地图都是陆地

    for i in range(n):
        for j in range(m):
            if grid[i][j] == 0:
                isAllGrid = False
            if not visited[i][j] and grid[i][j] == 1:
                count = 0
                dfs(grid, visited, i, j, mark)  # 深度优先搜索,标记岛屿
                gridNum[mark] = count  # 记录岛屿面积
                mark += 1  # 记录下一个岛屿编号

    if isAllGrid:  # 如果整个地图都是陆地
        print(n * m)  # 返回全面积
        return

    result = 0  # 记录最后结果
    visitedGrid = set()  # 标记访问过的岛屿

    for i in range(n):
        for j in range(m):
            if grid[i][j] == 0:
                count = 1
                visitedGrid.clear()
                for k in range(4):  # 检查四个方向
                    neari, nearj = i + dir[k][0], j + dir[k][1]
                    if not (0 <= neari < n and 0 <= nearj < m):  # 检查是否越界
                        continue
                    if grid[neari][nearj] in visitedGrid:  # 已访问过的岛屿不重复计算
                        continue
                    count += gridNum.get(grid[neari][nearj], 0)  # 相邻岛屿的面积累加
                    visitedGrid.add(grid[neari][nearj])  # 标记岛屿已访问
                result = max(result, count)  # 更新结果

    print(result)

if __name__ == "__main__":
    main()
  1. DFS标记岛屿:首先,代码通过DFS算法遍历整个网格,将所有连通的陆地单元格标记为相同的数字(称为“岛屿编号”或mark)。每个新发现的陆地区域从2开始编号,并在访问该区域的所有单元格时,将它们标记为当前的mark

  2. 记录岛屿面积:在DFS过程中,同时计数每个岛屿的单元格数量,并将这个数量与岛屿编号一起存储在字典gridNum中。

  3. 检查海水单元格周围:在DFS完成后,代码再次遍历整个网格。这一次,它专门检查海水单元格(grid[i][j] == 0)。

  4. 累加周围岛屿面积:对于每个海水单元格,代码检查其四个相邻单元格(上、下、左、右)。如果一个相邻单元格是陆地,且它的编号(即之前DFS过程中赋予的mark)不在当前的visitedGrid集合中,则将该岛屿的面积(从gridNum中获取)累加到count变量中,并将该岛屿编号添加到visitedGrid中,以避免重复计算。

  5. 更新最大结果:对于每个海水单元格,如果通过连接周围的岛屿,累加得到的面积大于当前记录的最大值result,则更新result

  6. 输出结果:最后,代码输出在整个网格中找到的,通过将一个海水单元格变成陆地而能够获得的最大岛屿面积。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1996364.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C++入门2

函数重载 函数重载&#xff1a;是函数的一种特殊情况&#xff0c;C允许在同一作用域中声明几个功能类似的同名函数&#xff0c;这 些同名函数的形参列表(参数个数 或 类型 或 类型顺序)不同&#xff0c;常用来处理实现功能类似数据类型 不同的问题 比如下面的 int add(int x…

数据结构和算法|递归算法那些事(递归算法的时间复杂度、尾递归优化、斐波那契数列)

对于文章的第一部分&#xff0c;递归算法的时间复杂度&#xff0c;来自于代码随想录文章:通过一道面试题目&#xff0c;讲一讲递归算法的时间复杂度&#xff01; 对于第二节尾递归优化来自于B站&#xff1a;尾递归优化&#xff1a;你的递归调用是如何被优化的&#xff1f; 文章…

Spring Boot - 通过ApplicationListener实现接口请求的性能监控

文章目录 概述1. ServletRequestHandledEvent事件2. 实现步骤3. 优缺点分析4. 测试与验证小结其他方案1. 自定义拦截器2. 性能监控平台3. 使用Spring Boot Actuator4. APM工具 概述 在Spring框架中&#xff0c;监控接口请求的性能可以通过ServletRequestHandledEvent事件实现。…

【Java日志系列】日志概述

目录 前言 一、日志概述 二、日志文件 1. 调试日志 2. 系统日志 三、日志框架 1. 日志框架的作用 2. 日志框架的价值 3. 市面上流行的日志框架 4. 日志门面和日志实现的区别 总结 前言 在软件开发中&#xff0c;日志记录是一项至关重要的任务。无论是简单的命令行应…

微服务架构-SpringCloud

1.单体应用架构 将项目所有模块(功能)打成jar或者war&#xff0c;然后部署一个进程。 优点&#xff1a; 部署简单&#xff1a;由于是完整的结构体&#xff0c;可以直接部署在一个服务器上即可。技术单一&#xff1a;项目不需要复杂的技术栈&#xff0c;往往一套熟悉的技术栈就…

Netty技术全解析:LineBasedFrameDecoder类深度解析

❃博主首页 &#xff1a; 「码到三十五」 &#xff0c;同名公众号 :「码到三十五」&#xff0c;wx号 : 「liwu0213」 ☠博主专栏 &#xff1a; <mysql高手> <elasticsearch高手> <源码解读> <java核心> <面试攻关> ♝博主的话 &#xff1a…

【leetcode】杨辉三角(Java语言描述)

杨辉三角 给定一个非负整数 numRows&#xff0c;生成「杨辉三角」的前 numRows 行。 在「杨辉三角」中&#xff0c;每个数是它左上方和右上方的数的和。 示例 1: 输入: numRows 5 输出: [[1],[1,1],[1,2,1],[1,3,3,1],[1,4,6,4,1]]示例 2: 输入: numRows 1 输出: [[1]] …

XIAOJUSURVEY 重磅升级,推出图形化逻辑编排能力

&#x1f389;&#x1f389;&#x1f389;XIAOJUSURVEY 是滴滴开源的企业级问卷系统&#xff0c;现已重磅升级&#xff01;&#xff01;&#xff01; 本次升级基于自研规则引擎&#xff0c;全面支持复杂的问卷逻辑编排&#xff0c;实现了显示逻辑与跳转逻辑的无缝整合。突破了…

MySQL Galera Cluster 部署与介绍

目录 主要特点 组件 一. 环境准备 二. 配置 1. 配置 galera1 主机的my.cnf的文件 2. 配置 galera2 主机的my.cnf的文件 3. 配置 galera3 主机的my.cnf的文件 4. 在给galera1 主机的my.cnf的文件增加节点 5. 写入数据验证同步 6. 配置 galera4 主机的my.cnf的文件 M…

线性回归Pytorch方法

借助 PyTorch 实现深度神经网络 - 线性回归 PyTorch 方法 - 第 3 周 | Coursera 随机梯度下降和数据加载器 在每个epoch中&#xff0c;使用一个样本进行更新的方法称为随机梯度下降&#xff0c;而使用所有样本进行更新的方法称为批量梯度下降。 随机梯度下降&#xff1a; 随…

第五代数字产业园入驻西安,西安国际数字影像产业园究竟能带来哪些颠覆性变革?

西安&#xff0c;这座承载着千年历史文化底蕴的古老城市&#xff0c;在时代的洪流中不断焕发出新的生机与活力。如今&#xff0c;西安第五代数字产业园入驻西安&#xff0c;犹如一颗璀璨的新星在这片土地上冉冉升起&#xff0c;为这座城市的发展注入了强大的动力。而在这一重大…

AFSim 仿真系统---- 通信、传感器与干扰系统方程

概述 本文档旨在描述在WSF中对象之间交互所使用的方程和算法。这包括&#xff1a; 传感器交互通信交互干扰&#xff08;干扰&#xff09;交互 常见无线电频率方程 WSF使用一套通用类来封装涉及无线电频率&#xff08;RF&#xff09;交互的组件&#xff08;实际上&#xff0…

基于B/S模式的JSP二手车交易网站

你好&#xff0c;我是计算机专业的学生&#xff0c;专注于Web开发。希望我的论文能够为您提供一些有价值的信息。 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;JSP技术 工具&#xff1a;ECLIPSE、Tomcat 系统展示 首页 用户界面 管理员界面 汽车评…

新加坡服务器延迟大吗?如何进行优化

新加坡服务器延迟大吗&#xff1f;新加坡服务器的延迟通常在全国平均延迟111ms左右&#xff0c;其中移动网络约为90ms&#xff0c;联通网络106ms&#xff0c;电信网络最低约为85ms。为了进行优化&#xff0c;一般可以采取使用CDN、优化路由线路、增加带宽和服务器升级等方法。 …

VBA高级应用30例应用3在Excel中的ListObject对象:创建表

《VBA高级应用30例》&#xff08;版权10178985&#xff09;&#xff0c;是我推出的第十套教程&#xff0c;教程是专门针对高级学员在学习VBA过程中提高路途上的案例展开&#xff0c;这套教程案例与理论结合&#xff0c;紧贴“实战”&#xff0c;并做“战术总结”&#xff0c;以…

Linux 内核源码分析---简单文件系统

顺序文件 debugfs 文件系统 允许只用几个函数调用&#xff0c;就实现一个双向的调试接口。 小的文件系统中的文件&#xff0c;通常用户层是 从头到尾顺序读取 的&#xff0c;其内容可能是遍历一些数据项创建的。 kprobe 机制包含了到上述 debugfs文件系统 的一个接口。一个顺…

【模电笔记】——集成运算放大电路

tips&#xff1a;本章节的笔记已经打包到word文档里啦&#xff0c;建议大家下载文章顶部资源&#xff08;有时看不到是在审核中&#xff0c;等等就能下载了。手机端下载后里面的插图可能会乱&#xff0c;建议电脑下载&#xff0c;兼容性更好且易于观看&#xff09;&#xff0c;…

利用学校资源访问scientdirect等国外数据库

就直接点view pdf这样的下载按钮&#xff0c;会让你输入组织&#xff0c;搜索找到学校的名字&#xff0c;接下来可以能会要求输入学校邮箱或者其他身份认证信息&#xff0c;最后就可以享受学校已经出过钱买的服务啦&#xff01;如果不用那么你每个学期大几千的学费简直是暴殄天…

定制你的项目工作流:最适合的文档管理解决方案

国内外主流的10款项目文档管理软件对比&#xff1a;PingCode、Worktile、Teambition、Tapd、Tower、Confluence、Notion、Dropbox Paper、Quip、Basecamp。 在面对项目管理的复杂性时&#xff0c;选择合适的文档管理工具可以显著提高效率和团队协作。许多团队在文档管理上遭遇混…

灰度宣布推出SUI加密投资信托基金

灰度&#xff0c;这家推出受欢迎的BTC和ETH交易所交易基金&#xff08;ETF&#xff09;的投资公司&#xff0c;于8月7日宣布将开始提供两种新的加密基金Grayscale Sui Trust和Grayscale Bittensor Trust&#xff0c;这些基金投资于Layer-1区块链Sui&#xff08;SUI&#xff09;…