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

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

101. 孤岛的总面积

本题要求找到不靠边的陆地面积,那么我们只要从周边找到陆地然后 通过 dfs或者bfs 将周边靠陆地且相邻的陆地都变成海洋,然后再去重新遍历地图 统计此时还剩下的陆地就可以了。

1、从左边和后边向中间遍历

2、从上边和下边向中间遍历

package mainimport ("fmt"
)func dfs(grid [][]int, x, y, n, m int) {if x < 0 || x >= n || y < 0 || y >= m || grid[x][y] != 1 {return}grid[x][y] = 2 // 标记为接触边缘的陆地dfs(grid, x+1, y, n, m)dfs(grid, x-1, y, n, m)dfs(grid, x, y+1, n, m)dfs(grid, x, y-1, n, m)
}func main() {var n, m intfmt.Scan(&n, &m)grid := make([][]int, n)for i := 0; i < n; i++ {grid[i] = make([]int, m)for j := 0; j < m; j++ {fmt.Scan(&grid[i][j])}}// 从左、右边界向中间遍历for i := 0; i < n; i++ {if grid[i][0] == 1 {dfs(grid, i, 0, n, m)}if grid[i][m - 1] == 1 {dfs(grid, i, m - 1, n, m)}}// 从上、下边界向中间遍历for j := 0; j < m; j++ {if grid[0][j] == 1 {dfs(grid, 0, j, n, m)}if grid[n - 1][j] == 1 {dfs(grid, n - 1, j, n, m)}} count := 0for i := 0; i < n; i++ {for j := 0; j < m; j++ {if grid[i][j] == 1 {count++}}}fmt.Println(count)
}

102. 沉没孤岛

思路依然是从地图周边出发,将周边空格相邻的陆地都做上标记,然后在遍历一遍地图,遇到 陆地 且没做过标记的,那么都是地图中间的 陆地 ,全部改成水域就行。

有的录友可能想,我再定义一个 visited 二维数组,单独标记周边的陆地,然后遍历地图的时候同时对 地图数组 和 数组visited 进行判断,决定 陆地是否变成水域。

这样做其实就有点麻烦了,不用额外定义空间了,标记周边的陆地,可以直接改陆地为其他特殊值作为标记。

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

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

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

package mainimport ("fmt"
)func dfs(grid [][]int, x, y, n, m int) {if x < 0 || x >= n || y < 0 || y >= m || grid[x][y] != 1 {return}grid[x][y] = 2 // 标记为接触边缘的陆地dfs(grid, x+1, y, n, m)dfs(grid, x-1, y, n, m)dfs(grid, x, y+1, n, m)dfs(grid, x, y-1, n, m)
}func main() {var n, m intfmt.Scan(&n, &m)grid := make([][]int, n)for i := 0; i < n; i++ {grid[i] = make([]int, m)for j := 0; j < m; j++ {fmt.Scan(&grid[i][j])}}// 第一步:从左、右边界上所有是 1 的位置开始 DFS 标记for i := 0; i < n; i++ {if grid[i][0] == 1 {dfs(grid, i, 0, n, m)}if grid[i][m-1] == 1 {dfs(grid, i, m-1, n, m)}}// 从上、下边界上所有是 1 的位置开始 DFS 标记for j := 0; j < m; j++ {if grid[0][j] == 1 {dfs(grid, 0, j, n, m)}if grid[n-1][j] == 1 {dfs(grid, n-1, j, n, m)}}// 第二步:沉没孤岛(grid[i][j] == 1),还原边界陆地(grid[i][j] == 2)for i := 0; i < n; i++ {for j := 0; j < m; j++ {if grid[i][j] == 1 {grid[i][j] = 0 // 沉没孤岛} else if grid[i][j] == 2 {grid[i][j] = 1 // 还原接触边界的陆地}}}// 输出矩阵,注意每个元素后都要有空格for i := 0; i < n; i++ {for j := 0; j < m; j++ {fmt.Printf("%d ", grid[i][j])}fmt.Println()}
}

103. 水流问题

首先读懂题目,水从高处流向低处,看看有没有一个坐标位置能同时到达第一和第二边界

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

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

然后两方都标记过的节点就是既可以流向第一组边界也可以流向第二组边界的节点

从第一组边界边上节点出发,如图: (图中并没有把所有遍历的方向都画出来,只画关键部分)

package mainimport ("fmt"
)// var dirs = [][]int{{0, 1}, {0, -1}, {1, 0}, {-1, 0}}// func dfs(matrix [][]int, visited [][]bool, x, y, n, m int) {
// 	visited[x][y] = true
// 	for _, dir := range dirs {
// 		nx := x + dir[0]
// 		ny := y + dir[1]
// 		if nx >= 0 && nx < n && ny >= 0 && ny < m &&
// 			!visited[nx][ny] &&
// 			matrix[nx][ny] >= matrix[x][y] {
// 			dfs(matrix, visited, nx, ny, n, m)
// 		}
// 	}
// }func dfs(matrix [][]int, visited [][]bool, x, y, n, m int) {visited[x][y] = truedirections := [][]int{{0,1},{1,0},{0,-1},{-1,0}}for _, d := range directions {nx, ny := x + d[0], y + d[1]if nx >= 0 && nx < n && ny >= 0 && ny < m {// 只有当相邻格子的高度 >= 当前格子的高度,水才能从边界流进去if !visited[nx][ny] && matrix[nx][ny] >= matrix[x][y] {dfs(matrix, visited, nx, ny, n, m)}}}
}func main() {var n, m intfmt.Scan(&n, &m)matrix := make([][]int, n)for i := 0; i < n; i++ {matrix[i] = make([]int, m)for j := 0; j < m; j++ {fmt.Scan(&matrix[i][j])}}// 初始化访问标记数组canReachFirst := make([][]bool, n)canReachSecond := make([][]bool, n)for i := 0; i < n; i++ {canReachFirst[i] = make([]bool, m)canReachSecond[i] = make([]bool, m)}// 从第一组边界出发(左边 + 上边)for i := 0; i < n; i++ {dfs(matrix, canReachFirst, i, 0, n, m) // 左边}for j := 0; j < m; j++ {dfs(matrix, canReachFirst, 0, j, n, m) // 上边}// 从第二组边界出发(右边 + 下边)for i := 0; i < n; i++ {dfs(matrix, canReachSecond, i, m-1, n, m) // 右边}for j := 0; j < m; j++ {dfs(matrix, canReachSecond, n-1, j, n, m) // 下边}// 输出能同时到达两个边界的坐标for i := 0; i < n; i++ {for j := 0; j < m; j++ {if canReachFirst[i][j] && canReachSecond[i][j] {fmt.Println(i, j)}}}
}

104. 建造最大岛屿

做好标记

其实每次深搜遍历计算最大岛屿面积,我们都做了很多重复的工作。

只要用一次深搜把每个岛屿的面积记录下来就好。

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

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

拿如下地图的岛屿情况来举例: (1为陆地)

第一步,则遍历地图,并将岛屿的编号和面积都统计好,过程如图所示:

// 先遍历整张地图,找出所有的岛屿,并标记每个岛屿的编号及其面积。// 用一个 islandId 数组记录每个格子属于哪个岛屿。// 然后遍历所有水格(值为0的格子),尝试将它变为1,然后查看它四周是否有不同编号的岛屿,合并这些岛屿面积 +1。// 取最大值返回。package mainimport ("fmt")var dirs = [][]int{{0, 1}, {0, -1}, {1, 0}, {-1, 0}}var grid [][]intvar islandId [][]intfunc dfs (x, y, id, n, m int) int {if x < 0 || x >= n || y < 0 || y >= m || grid[x][y] != 1 {return 0}grid[x][y] = 2islandId[x][y] = idarea := 1for _, dir := range dirs {area += dfs(x + dir[0], y + dir[1], id, n, m)}return area}func main() {var n, m intfmt.Scan(&n, &m)// 初始化矩阵和标记数组grid = make([][]int, n)islandId = make([][]int, n)for i := 0; i < n; i++ {grid[i] = make([]int, m)islandId[i] = make([]int, m)for j := 0; j < m; j++ {fmt.Scan(&grid[i][j])}}// 岛屿编号和面积映射id := 2areaMap := make(map[int]int)// 找出所有岛屿及面积for i := 0; i < n; i++ {for j := 0; j < m; j++ {if grid[i][j] == 1 {area := dfs(i, j, id, n, m)areaMap[id] = areaid++}}}maxArea := 0for i := 0; i < n; i++ {for j := 0; j < m; j++ {if islandId[i][j] != 0 {if areaMap[islandId[i][j]] > maxArea {maxArea = areaMap[islandId[i][j]]}continue}// 水格,尝试变为陆地seen := map[int]bool{}area := 1for _, d := range dirs {x, y := i+d[0], j+d[1]if x >= 0 && x < n && y >= 0 && y < m {id := islandId[x][y]if id != 0 && !seen[id] {area += areaMap[id]seen[id] = true}}}if area > maxArea {maxArea = area}}}fmt.Println(maxArea)}

相关文章:

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

101. 孤岛的总面积 本题要求找到不靠边的陆地面积&#xff0c;那么我们只要从周边找到陆地然后 通过 dfs或者bfs 将周边靠陆地且相邻的陆地都变成海洋&#xff0c;然后再去重新遍历地图 统计此时还剩下的陆地就可以了。 1、从左边和后边向中间遍历 2、从上边和下边向中间遍历…...

仿modou库one thread one loop式并发服务器

源码&#xff1a;田某super/moduo 目录 SERVER模块&#xff1a; Buffer模块&#xff1a; Socket模块&#xff1a; Channel模块&#xff1a; Connection模块&#xff1a; Acceptor模块&#xff1a; TimerQueue模块&#xff1a; Poller模块&#xff1a; EventLoop模块&a…...

MNIST 数据集 与 TFOD API

此处给出我在进行毕业设计过程中写的三份脚本&#xff0c;作为demo 展示模型的预处理&#xff0c;输出信息提取和TFOD API的应用。 script1 加载本地的MNIST模型&#xff0c;对本地的手写数字进行推理 # test the validation of the saved file and the camera import cv2 i…...

SpringSecurity6.0 通过JWTtoken进行认证授权

之前写过一个文章&#xff0c;从SpringSecurity 5.x升级到6.0&#xff0c;当时是为了配合公司的大版本升级做的&#xff0c;里面的各项配置都是前人留下来的&#xff0c;其实没有花时间进行研究SpringSecurity的工作机制。现在新东家有一个简单的系统要搭建&#xff0c;用户的认…...

【Java】Maven

一、概念 是一个项目管理和构建工具&#xff0c;它基于项目对象模型&#xff08;POM&#xff09;的概念&#xff0c;通过一小段描述信息来管理项目的构建。 二、Maven坐标 <groupId>com.itheima</groupId><artifactId>maven-project01</artifactId>&…...

第十五届蓝桥杯PythonC组题解

A题&#xff1a;拼正方形 问题描述 给定一定数量的 22 和 11 的方块&#xff0c;求能拼出的最大正方形边长。 解题思路 二分法&#xff1a;将奇数和偶数边长分开处理&#xff0c;通过二分法寻找最大满足条件的边长。面积验证&#xff1a;总方块面积需大于等于目标正方形面积…...

MATLAB中plot函数的详细参数表

LineSpec - 线型、标记和颜色 线型说明-实线--虚线:点线-.点划线 标记说明o圆圈加号*星号.点x叉号_水平线条|垂直线条s方形d菱形^上三角v下三角>右三角<左三角p五角形h六角形 颜色说明 y 黄色 m 品红色 c 青蓝色 r 红色 g 绿色 b 蓝色 w 白色 k 黑色 MarkerFaceColor…...

R语言赋能气象水文科研:从多维数据处理到学术级可视化

全球气候变化加剧了极端天气与水文事件的复杂性&#xff0c;气象卫星、雷达、地面观测站及水文传感器每天产生TB级‌时空异质数据‌。传统研究常面临四大瓶颈&#xff1a; ‌数据清洗低效‌&#xff1a;缺失值、异常值处理耗时&#xff1b;‌时空分析模型构建复杂‌&#xff1…...

虚拟试衣间-云尚衣橱小程序-衣橱管理实现

衣橱管理实现 目标 (Goal): 用户 (User): 能通过 UniApp 小程序上传衣服图片。 后端 (Backend): 接收图片,存到云存储,并将图片信息(URL、用户ID等)存入数据库。 用户 (User): 能在小程序里看到自己上传的所有衣服图片列表。 技术栈细化 (Refined Tech Stack for this Pha…...

BGP路由协议之属性2

Orgin 起源 公认必遵属性 起源名称标记描述IGPi如果路由是由始发的 BGP 路由器使用 network 命令注入到 BGP 的&#xff0c;那么该 BGP 路由的 origin 属性为 IGPEGPe如果路由是通过 EGP 学习到的&#xff0c;那么该 BGP 路由的 Origin 属性为 EGPIncomplete?如果路由是通过…...

纯个人整理,蓝桥杯使用的算法模板day2(0-1背包问题),手打个人理解注释,超全面,且均已验证成功(附带详细手写“模拟流程图”,全网首个

算法索引 01背包优化前空间优化版&#xff08;使用一维数组&#xff09;优化后的模拟流程图为何优化后&#xff0c;j不能使用正序遍历模拟流程图 代码对应实现案例 01背包 优化前 /*** 0-1背包问题解法&#xff08;与下方代码表格示例对应&#xff0c;已模拟验证&#xff09;*…...

算法与数据结构线性表之栈和队列

Hello大家好&#xff01; 很高兴与大家见面&#xff01; 给生活添点快乐&#xff0c;开始今天的编程之路。 我的博客:<但愿. 我的专栏:C语言、题目精讲、算法与数据结构、C 欢迎点赞&#xff0c;关注 一 栈 1概念&#xff1a;栈是⼀种特殊的线性表&#xff0c;其只允许…...

python应用之使用pdfplumber 解析pdf文件内容

目录标题 一. 通过 pdfplumber.open() 解析复杂PDF&#xff1a;1-2. 报错&#xff1a;V2 &#xff1a; 1-3. v3 使用tk 库&#xff0c;弹框选择文件运行环境准备完整代码保存运行测试步骤方式二&#xff1a;命令行方式&#xff08;适用于自动化&#xff09; 测试用例示例常见问…...

laravel update报In PackageManifest.php line 122:Undefined index: name 错误的解决办法

用 composer 更新 laravel依赖包时报错 > Illuminate\Foundation\ComposerScripts::postAutoloadDump > Illuminate\Foundation\ComposerScripts::postAutoloadDump > php artisan package:discover --ansiIn PackageManifest.php line 122:Undefined index: nameScr…...

Vue中使用antd-table组件实现数据选择、禁用、已选择禁用-demo

实现案例 实现过程 表格代码 关键代码 :row-selection="rowSelection" <div><div class="flex items-center justify-between pt-[24px] pb-[16px]"><p>已选:{{ keysNum }}</p><a-input-search v-model:value="productN…...

C语言--统计输入字符串中的单词个数

输入 输入&#xff1a;大小写字母以及空格&#xff0c;单词以空格分隔 输出&#xff1a;单词个数 代码 如果不是空格且inWord0说明是进入单词的第一个字母&#xff0c;则单词总数加一。 如果是空格&#xff0c;证明离开单词&#xff0c;inWord 0。 #include <stdio.h&g…...

Kubernetes 集群搭建(三):使用dashboard用户界面(需要访问外网获取yaml)

&#xff08;一&#xff09;简介 K8s Dashboard是Kubernetes提供的一种基于Web的用户界面工具&#xff0c;用于可视化地管理和监控Kubernetes集群 主要功能&#xff1a; 资源查看与管理&#xff1a; 查看Kubernetes集群中的各种资源&#xff0c;如节点、Pod、服务、部署等。 对…...

Debian 12 服务器搭建Beego环境

一、Debian 12系统准备 1.更新系统 #apt update && apt upgrade -y 2.安装基础工具 #apt install -y git curl wget make gcc 二、安装Go环境 Go语言的镜像官网&#xff1a;https://golang.google.cn/ 1.下载go最新版 #cd /usr/local/src #wget -o https://golang.go…...

游戏引擎学习第208天

运行游戏并回顾我们的情况 今天&#xff0c;我们将继续完成之前中断的调试输出工作。最近的工作偏离了一些&#xff0c;展示了如何进行元编程的实践&#xff0c;主要涉及了一个小的解析器。尽管这个解析器本身是一个玩具&#xff0c;但它展示了如何完成一个完整的循环&#xf…...

【在校课堂笔记】Python 第 7 节课 总结

- 第 85 篇 - Date: 2025 - 04 - 06 Author: 郑龙浩/仟墨 【Python 在校课堂笔记】 南山-第 7 节课 上课时间: 2025-03-27 文章目录 南山-第 7 节课一 99乘法表 –> 三角二 函数1 已接触的函数&#xff0c;部分举例2 自定函数的定义与使用自定义函数:举例 3 带参数的4 阶乘…...

评价区动态加载是怎么实现的?

淘宝商品评价区的动态加载是通过一系列前端技术和后端接口实现的&#xff0c;其核心目的是提升用户体验和页面性能。以下是其实现原理和关键技术的详细解析&#xff1a; 1. 前端实现&#xff1a;AJAX 和 JavaScript 淘宝利用 AJAX&#xff08;Asynchronous JavaScript and XM…...

【 <二> 丹方改良:Spring 时代的 JavaWeb】之 Spring Boot 中的监控:使用 Actuator 实现健康检查

<前文回顾> 点击此处查看 合集 https://blog.csdn.net/foyodesigner/category_12907601.html?fromshareblogcolumn&sharetypeblogcolumn&sharerId12907601&sharereferPC&sharesourceFoyoDesigner&sharefromfrom_link <今日更新> 一、引子&…...

蓝桥杯—数字接龙(dfs+减枝)

一.题目 二.思路 一看就是迷宫问题的变种&#xff0c;从左上角到达右下角&#xff0c;要解决 1.8个方向的方向向量&#xff0c;用dx&#xff0c;dy数组代表方向向量 2.要按照一个规律的数值串进行搜索0&#xff0c;1&#xff0c;2&#xff0c;k-1&#xff0c;0&#xff0c;1…...

Docker与VNC的使用

https://hub.docker.com/r/dorowu/ubuntu-desktop-lxde-vnc 下载nvc 客户端 https://downloads.realvnc.com/download/file/viewer.files/VNC-Viewer-7.12.0-Windows.exe 服务端 docker pull dorowu/ubuntu-desktop-lxde-vnc#下载成功 docker pull dorowu/ubuntu-desktop-l…...

C++——清明

#include <iostream> #include <cstring> #include <cstdlib> #include <unistd.h> #include <sstream> #include <vector> #include <memory> #include <ctime>using namespace std;class Weapon; // 前置声明class Hero{ pr…...

Unity ViewportConstraint

一、组件功能概述 ViewportConstraint是一个基于世界坐标的UI边界约束组件&#xff0c;主要功能包括&#xff1a; 将UI元素限制在父容器范围内支持自定义内边距&#xff08;padding&#xff09;可独立控制水平和垂直方向的约束 二、实现原理 1. 边界计算&#xff08;世界坐…...

Gin、Echo 和 Beego三个 Go 语言 Web 框架的核心区别及各自的优缺点分析,结合其设计目标、功能特性与适用场景

1. Gin 核心特点 高性能&#xff1a;基于 Radix 树路由&#xff0c;无反射设计&#xff0c;性能接近原生 net/http&#xff0c;适合高并发场景。轻量级&#xff1a;仅提供路由、中间件、请求响应处理等基础功能&#xff0c;依赖少。易用性&#xff1a;API 设计简洁直观&#…...

ffmpeg视频转码相关

ffmpeg视频转码相关 简介参数 实战举栗子获取视频时长视频转码mp4文件转为hls m3u8 ts等文件图片转视频抽取视频第一帧获取基本信息 转码日志输出详解转码耗时测试 简介 FFmpeg 是领先的多媒体框架&#xff0c;能够解码、编码、 转码、复用、解复用、流、过滤和播放 几乎所有人…...

手搓多模态-06 数据预处理

前情回顾 我们目前实现了视觉模型的编码器部分&#xff0c;然而&#xff0c;我们所做的是把一张图片编码嵌入成了许多个上下文相关的嵌入向量&#xff0c;然而我们期望的是一张图片用一个向量来表示&#xff0c;从而与文字的向量做点积形成相似度&#xff08;参考手搓多模态-01…...

HCIP【路由过滤技术(详解)】

目录 1 简介 2 路由过滤方法 3 路由过滤工具 3.1 静默接口 3.2 ACL 3.3 地址前缀列表 3.4 filter-policy 3.4.1 filter-policy过滤接收路由&#xff08;以RIP为例&#xff09; 3.4.2 filter-policy过滤接收路由&#xff08;以OSPF为例&#xff09; 1 简介 路由过滤技术…...