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

代码随想录算法训练营第五十六天| 图论2—卡码网99. 岛屿数量(dfs bfs)

假期归来继续刷题,图论第二天,主要是进一步熟悉dfs 和 bfs 的运用。

99. 岛屿数量(dfs)

99. 岛屿数量

ACM模式还是需要练,不过现在输入输出的感觉已经比较熟悉了。首先是要按照输入搭建一个grid,然后有一个对应的全是False 的 visit。

关于方向就只有上下左右四个,如果可以走斜向,方向就变成八个了。递归的过程其实比较好理解,就是当前x,y逐步相加,如果越界了就continue,然后如果碰到了grid中为1但没有visit的,就变成visit继续向后递归,当四边都没法符合判断条件的话就进行返回,这就是dfs顺着一条路走下去的思想。

然后是主函数中的调用,当碰到第一个符合条件的地块开始,并计数,记得同时将这块变为True,因为dfs函数里直接是从下一个地块开始转换的。然后不停递归,当结束的时候,就继续回到主函数的遍历中,去测下一个符合if grid[i][j] == 1 and not visited[i][j]:条件的地块,当碰到就是第二块岛,记得将数量+1然后继续递归。

简单理解,主函数中,i,j二次遍历,一旦找到一个为1的地块便计数+1,同时dfs开始,当dfs遍历完之后,i,j继续遍历,这时候如果遍历到之前dfs遍历的地块,也会因为visit中为True而不会开始dfs。可以想象成发现一个起点,dfs开始逐步扩散发掘所有连着的地块。

# dfs方法一
direction = [[0, 1], [1, 0], [0, -1], [-1, 0]] def dfs(grid, visited, x, y):for i, j in direction:next_x = x + inext_y = y + jif next_x < 0 or next_x >= len(grid) or next_y < 0 or next_y >= len(grid[0]):continueif not visited[next_x][next_y] and grid[next_x][next_y] == 1:visited[next_x][next_y] = Truedfs(grid, visited, next_x, next_y)if __name__ == '__main__':  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 = 0for i in range(n):for j in range(m):# 判断:如果当前节点是陆地,res+1并标记访问该节点,使用深度搜索标记相邻陆地。if grid[i][j] == 1 and not visited[i][j]:res += 1visited[i][j] = Truedfs(grid, visited, i, j)print(res)

dfs的版本二,变化不大,总体方法更符合之前回溯的模板,即参数-终止条件-单层逻辑。

版本一的写法是 :下一个节点是否能合法已经判断完了,传进dfs函数的就是合法节点。

版本二的写法是:不管节点是否合法,上来就dfs,然后在终止条件的地方进行判断,不合法再return。

理论上来讲,版本一的效率更高一些,因为避免了 没有意义的递归调用,在调用dfs之前,就做合法性判断。 但从写法来说,可能版本二 更利于理解一些。(不过其实都差不太多)

direction = [[0, 1], [1, 0], [0, -1], [-1, 0]] def dfs(grid, visited, x, y):# 与版本一的差别,在调用前增加判断终止条件if visited[x][y] or grid[x][y] == 0:returnvisited[x][y] = Truefor i, j in direction:next_x = x + inext_y = y + jif next_x < 0 or next_x >= len(grid) or next_y < 0 or next_y >= len(grid[0]):continuedfs(grid, visited, next_x, next_y)if __name__ == '__main__':# 版本二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 = 0for i in range(n):for j in range(m):# 判断:如果当前节点是陆地,res+1并标记访问该节点,使用深度搜索标记相邻陆地。if grid[i][j] == 1 and not visited[i][j]:res += 1dfs(grid, visited, i, j)print(res)

99. 岛屿数量(bfs)

深搜是一条路走到头,广搜则是一圈一圈的扩散,可以类比为二叉树的层序遍历,原本是每个节点有左右两个子节点,现在变成每个地块有上下左右四个地块。

在bfs函数里,记住每开始一次bfs,要重置一次que,然后将当前的地块x,y 加入队列,并在visit中变成True。之后便是弹出,符合条件加入,重复直到队列为空。

之后主函数调用则是一样的思路,类似发现一个起点,然后一圈一圈开始扩散,直到无法扩散,便开始遍历寻找下一个岛屿的起点。

from collections import deque
directions = [[0, 1], [1, 0], [0, -1], [-1, 0]]
def bfs(grid, visited, x, y):que = deque([])que.append([x,y])visited[x][y] = Truewhile que:cur_x, cur_y = que.popleft()for i, j in directions:next_x = cur_x + inext_y = cur_y + jif next_y < 0 or next_x < 0 or next_x >= len(grid) or next_y >= len(grid[0]):continueif not visited[next_x][next_y] and grid[next_x][next_y] == 1: visited[next_x][next_y] = Trueque.append([next_x, next_y])if __name__ == "__main__":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 = 0for i in range(n):for j in range(m):if grid[i][j] == 1 and not visited[i][j]:res += 1bfs(grid, visited, i, j)print(res)

http://www.dtcms.com/a/174142.html

相关文章:

  • 养生融入生活,畅享健康人生
  • MySQL8查询某个JSON类型的字段中出现过的所有键名(json key name)并去重返回
  • conda虚拟环境相关操作
  • 第三章:langchain加载word文档构建RAG检索教程(基于FAISS库为例)
  • Spring Boot项目集成Aviator实现成本计算模块
  • 【阿里云大模型高级工程师ACP习题集】3 总结与展望
  • vscode远程服务器连接----过程尝试写入的管道不存在
  • 修改MySQL枚举类型添加‘location‘值
  • 【AI】Ubuntu 22.04 evalscope 模型评测 Qwen3-4B-FP8
  • Linux——https基础理论
  • 【AI论文】FormalMATH:大型语言模型形式化数学推理能力基准测试
  • C语言内存函数及大小端字节序!
  • Mysql order by 用法
  • Vue + Element UI 表单弹窗输入法卡顿问题解决方案
  • 用 Tailwind CSS 优化你的 Vue 3 项目! ! !
  • 计算机硬件:AMD X670E与B650主板的PCIe通道分配
  • 在 Laravel 12 中实现 WebSocket 通信时进行身份验证
  • 水质监控预警管理平台
  • 构建 Web 浏览 AI Agent:Pydantic + MCP 实现指南
  • C#学习第21天:安全与加密(Security and Cryptography)
  • Linux/AndroidOS中进程间的通信线程间的同步 - 虚拟内存操作
  • 企业级RAG架构设计:从FAISS索引到HyDE优化的全链路拆解,金融/医疗领域RAG落地案例与避坑指南(附架构图)
  • PCIe - ZCU106(RC) + KU5P(EP) + 固化
  • 利用 Kali Linux 进行信息收集和枚举
  • 用python实现鼠标监听与手势交互
  • 【KWDB 创作者计划】一文掌握KWDB的时序表管理
  • iOS与HTTPS抓包调试小结
  • QT生成保存 Excel 文件的默认路径,导出的文件后缀自动加(1)(2)等等
  • 上传下载接口
  • 02 mysql 管理(Windows版)