笔记:代码随想录算法训练营day57:99.岛屿数量 深搜、岛屿数量 广搜、100.岛屿的最大面积
学习资料:代码随想录
注:文中含大模型生成内容
99. 岛屿数量
卡码网题目链接(ACM模式)
先看深搜方法:找到未标标记过的说明找到一片陆地的或者一片陆地的一个角落,dfs搜索是寻找相连接的陆地其余部分并做好标记
#include <iostream>
#include <vector>
using namespace std;int direction[4][2]={0,1,-1,0,0,-1,1,0};void dfs(const vector<vector<int>>& B612,vector<vector<bool>>& visited,int x,int y){ //visited数组不能被声明为const,因为要改动int nextx,nexty;for(int i=0;i<4;i++){ //无需终止条件,在递归函数中,当当前调用的所有循环(或所有条件分支)都处理完后,函数会自动返回到上一级的调用处。这就是递归调用栈的工作方式nextx=direction[i][0]+x;nexty=direction[i][1]+y;if(nextx>=B612.size() || nextx<0 || nexty>=B612[0].size() || nexty<0) continue;else if(visited[nextx][nexty]==false&&B612[nextx][nexty]==1){visited[nextx][nexty]=true;dfs(B612,visited,nextx,nexty);}}
}int main(){int N,M;cin>>N>>M; //要有先输入参数再建立数组的意识vector<vector<int>> B612(N,vector<int>(M,0));for(int i=0;i<N;i++){for(int j=0;j<M;j++){cin>>B612[i][j];}}vector<vector<bool>> visited(N,vector<bool>(M,false));int result=0;
// 查找陆地过程for(int i=0;i<N;i++){for(int j=0;j<M;j++){if(B612[i][j]==1&&!visited[i][j]){ //遇到未访问过的陆地result++;visited[i][j]=true;dfs(B612,visited,i,j); //递归查找相连的陆地}}}cout<<result<<endl;
}
深搜还有第二种写法,加上了终止条件,此时就不能在深搜函数之前判断并修改visited了,这样会到达终止条件。正确做法为判断为到达终止条件后再修改visited。这样在dfs函数内部调用自己之前也就不用修改visited了,统一在调用函数初期修改
#include <iostream>
#include <vector>
using namespace std;int direction[4][2]={0,1,-1,0,0,-1,1,0};void dfs(const vector<vector<int>>& B612,vector<vector<bool>>& visited,int x,int y){ //visited数组不能被声明为const,因为要改动if(visited[x][y]==true || B612[x][y]==0) return;visited[x][y]=true;int nextx,nexty;for(int i=0;i<4;i++){ nextx=direction[i][0]+x;nexty=direction[i][1]+y;if(nextx>=B612.size() || nextx<0 || nexty>=B612[0].size() || nexty<0) continue;dfs(B612,visited,nextx,nexty);}
}int main(){int N,M;cin>>N>>M; //要有先输入参数再建立数组的意识vector<vector<int>> B612(N,vector<int>(M,0));for(int i=0;i<N;i++){for(int j=0;j<M;j++){cin>>B612[i][j];}}vector<vector<bool>> visited(N,vector<bool>(M,false));int result=0;
// 查找陆地过程for(int i=0;i<N;i++){for(int j=0;j<M;j++){if(B612[i][j]==1&&!visited[i][j]){ //遇到未访问过的陆地result++;// visited[i][j]=true;dfs(B612,visited,i,j); //递归查找相连的陆地}}}cout<<result<<endl;
}
广搜需要显性借助队列来记录一下,深搜是隐形地使用栈
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
int dir[4][2]={0,1,-1,0,0,-1,1,0};
void bfs(const vector<vector<int>>& B612,vector<vector<bool>>& visited,int x,int y){queue<pair<int,int>> que;que.push({x,y});visited[x][y]=true;int xnext,ynext;while(!que.empty()){pair<int,int> cur;cur = que.front();que.pop(); for(int i=0;i<4;i++){xnext=cur.first+dir[i][0];ynext=cur.second+dir[i][1];if(xnext<0||xnext>=B612.size()||ynext<0||ynext>=B612[0].size()) continue;if(visited[xnext][ynext]==false&&B612[xnext][ynext]==1){que.push({xnext,ynext});visited[xnext][ynext]=true;}}}
}
int main(){int N,M;cin>>N>>M;vector<vector<int>> B612(N,vector<int>(M,0));for(int i=0;i<N;i++){for(int j=0;j<M;j++){cin>>B612[i][j];}}vector<vector<bool>> visited(N,vector<bool>(M,0));int result = 0;for(int i=0;i<N;i++){for(int j=0;j<M;j++){if(B612[i][j]==1&&visited[i][j]==false){result++;bfs(B612,visited,i,j);}}}cout<<result<<endl;
}
注意广搜的visited的操作时机,在每一次push之后
99. 岛屿数量
卡码网题目链接(ACM模式)
同样还是两种深搜写法和一种广搜写法,
#include <iostream>
#include <vector>
using namespace std;int dir[4][2]={0,1,-1,0,0,-1,1,0};
int count;void dfs(const vector<vector<int>>& maldives,vector<vector<bool>>& visited,int x,int y){int xnext,ynext;for(int i=0;i<4;i++){xnext=x+dir[i][0];ynext=y+dir[i][1];if(xnext>=maldives.size()||xnext<0||ynext>=maldives[0].size()||ynext<0) continue;if(visited[xnext][ynext]==false&&maldives[xnext][ynext]==1){count++;visited[xnext][ynext]=true;dfs(maldives,visited,xnext,ynext);}}
}int main(){int m,n;cin>>n>>m;vector<vector<int>> maldives(n,vector<int>(m,0));for(int i=0;i<n;i++){for(int j=0;j<m;j++){cin>>maldives[i][j];}}vector<vector<bool>> visited(n,vector<bool>(m,0));int result =0;for(int i=0;i<n;i++){for(int j=0;j<m;j++){if(maldives[i][j]==1&&visited[i][j]==false){count=1;visited[i][j]=true;dfs(maldives,visited,i,j);result=max(count,result);//cout<<result<<endl;}}}cout<<result<<endl;
}
#include <iostream>
#include <vector>
using namespace std;int dir[4][2]={0,1,-1,0,0,-1,1,0};
int count;void dfs(const vector<vector<int>>& maldives,vector<vector<bool>>& visited,int x,int y){if(visited[x][y]==true||maldives[x][y]==0) return;visited[x][y]=true;count++;int xnext,ynext;for(int i=0;i<4;i++){xnext=x+dir[i][0];ynext=y+dir[i][1];if(xnext>=maldives.size()||xnext<0||ynext>=maldives[0].size()||ynext<0) continue;//count++;//visited[xnext][ynext]=true;dfs(maldives,visited,xnext,ynext);}
}int main(){int m,n;cin>>n>>m;vector<vector<int>> maldives(n,vector<int>(m,0));for(int i=0;i<n;i++){for(int j=0;j<m;j++){cin>>maldives[i][j];}}vector<vector<bool>> visited(n,vector<bool>(m,0));int result =0;for(int i=0;i<n;i++){for(int j=0;j<m;j++){if(maldives[i][j]==1&&visited[i][j]==false){count=0;//visited[i][j]=true;dfs(maldives,visited,i,j);result=max(count,result);}}}cout<<result<<endl;
}
注意count的操作和visited是在一起的,即找到后,标记+记录
#include <iostream>
#include <vector>
#include <queue>
using namespace std;int dir[4][2]={0,1,-1,0,0,-1,1,0};
int count;void bfs(const vector<vector<int>>& maldives,vector<vector<bool>>& visited,int x,int y){queue<pair<int,int>> que;que.push({x,y});visited[x][y]=true;count++;while(!que.empty()){pair<int,int> cur = que.front();que.pop();for(int i=0;i<4;i++){int xnext=cur.first+dir[i][0];int ynext=cur.second+dir[i][1];if(xnext<0||xnext>=maldives.size()||ynext<0||ynext>=maldives[0].size()) continue;if(visited[xnext][ynext]==false&&maldives[xnext][ynext]==1){que.push({xnext,ynext});visited[xnext][ynext]=true;count++;}}}
}int main(){int m,n;cin>>n>>m;vector<vector<int>> maldives(n,vector<int>(m,0));for(int i=0;i<n;i++){for(int j=0;j<m;j++){cin>>maldives[i][j];}}vector<vector<bool>> visited(n,vector<bool>(m,0));int result =0;for(int i=0;i<n;i++){for(int j=0;j<m;j++){if(maldives[i][j]==1&&visited[i][j]==false){count=0;//visited[i][j]=true;bfs(maldives,visited,i,j);result=max(count,result);}}}cout<<result<<endl;
}
深搜两种写法的区别:
- 在版本二中,dfs 函数自身判断当前结点是否满足递归条件,如果不满足则立即返回,这就保证了每个进入 dfs 的结点都一定被计数一次。
- 而在版本一中,dfs 函数假定传入的结点已经被处理(已经标记和计数),它只关注于后续的邻居。
加上返回条件后,你让 DFS 函数自己负责判断当前节点是否有效并进行标记和计数,这就改变了 DFS 的“契约”。
-
原来的写法(版本一):
调用者(主函数)已经预先判断、标记并计数了起始节点,所以 DFS 只处理“邻居”。因此,DFS 函数没有对传入的节点再做一次有效性检查,也不会再重复计数。 -
加上返回条件的写法(版本二):
你让 DFS 函数在入口处立即检查:如果当前节点已经访问过或者是水(无效),就直接返回;否则,立即标记并计数。
这样做使得 DFS 成为一个更“通用”的函数,可以被任意调用,而不必依赖调用者事先处理。
但这也意味着主函数不应在调用 DFS 前预先计数,否则就会重复计数。
简单说,加上返回条件后,DFS 的职责就从“仅扩展邻居”变为“全权负责当前节点及其邻居的处理”,这就要求你调整计数逻辑和调用方式,确保每个节点只被处理和计数一次。
换句话说,加入返回条件改变了函数的接口和行为约定(契约),因此需要相应地改变代码结构
假如想又有终止条件又提前处理,冲突点在于:
如果你混用两种做法,即在主函数中预先判断和标记 A,又在 DFS 中加入终止条件判断,就会出现以下两种潜在问题:
-
重复计数(双重处理):
- 假设主函数预先对 A 标记并计数,然后调用 DFS(A)。
- DFS 入口处检查到
visited[A]已经为 true(因为主函数预先标记了),那么 DFS 立即返回,不再扩展 A 的邻居。 - 结果:A 的邻居没有被搜索到,整个岛屿可能无法正确计数。
或者反过来,如果你不预先标记但又在 DFS 内部计数,而主函数又对 A 进行了计数,就会导致 A 被计数两次。
-
跳过递归扩展:
- 如果你预先标记了 A,而 DFS 又有
if(visited[x][y] ...) return;的终止条件,那么当 DFS 被调用时,它会发现 A 已经被标记,然后直接返回,不会继续对 A 的邻居进行递归调用。 - 这会使得整个 DFS 搜索提前终止,导致岛屿中的其他陆地节点被遗漏,计数结果不正确。
- 如果你预先标记了 A,而 DFS 又有
相关文章:
笔记:代码随想录算法训练营day57:99.岛屿数量 深搜、岛屿数量 广搜、100.岛屿的最大面积
学习资料:代码随想录 注:文中含大模型生成内容 99. 岛屿数量 卡码网题目链接(ACM模式) 先看深搜方法:找到未标标记过的说明找到一片陆地的或者一片陆地的一个角落,dfs搜索是寻找相连接的陆地其余部分并…...
【小也的Java之旅系列】01 分布式、集群、微服务的区别
前言 做Java开发多年,一直以来都有想把Java做成一个系列的想法,最近整理自己的笔记发现有很多值得写的内容,但这些内容又往往杂乱不堪。CSDN上有很多高质量的Java博客,但大多不是从一个人成长的角度去写的。而我们——一个技术人…...
基于视觉的核桃分级与套膜装置研究(大纲)
基于视觉的核桃分级与套膜装置研究:从设计到实现的完整指南 (SolidWorks、OpenCV、STM32开发实践) 🌟 项目背景与目标 1.1 为什么选择视觉分级与套膜? 产业痛点: 中国核桃年产量全球第一,但…...
JimuReport与deepseek结合,颠覆现有BI模式
在数字化转型的浪潮中,企业对数据的依赖程度越来越高,如何高效地分析和利用数据成为关键。JimuReport凭借其强大的报表设计能力和灵活的数据处理功能,已经成为众多企业的首选工具。如今,它即将与DeepSeek深度结合,为企…...
大白话详细解读函数之柯里化
1. 函数柯里化是什么? 函数柯里化是一种将多参数函数转换成一系列单参数函数的技术。简单来说,就是把一个接收多个参数的函数,变成每次只接收一个参数,并返回一个新函数,直到所有参数都接收完毕,最后返回结…...
11、STL中的set使用方法
一、了解 set 是 C 标准模板库(STL)中提供的有序关联容器之一。基于红黑树(Red-Black Tree)实现,用于存储一组唯一的元素,并按照元素的值进行排序。 set的特性 唯一性 键是唯一的。无重复。 有序性 按升序…...
git 子模块的使用
1. 子模块的核心概念 独立性:子模块是一个独立的 Git 仓库,有自己的提交历史和分支。 指针机制:主仓库仅记录子模块的特定提交(而不是分支),确保代码版本可控。 适用场景:依赖第三方库、多项目…...
vsftpd服务权限配置
主配置文件:/etc/vsftpd/vsftpd.conf anonymous_enableYES #是否启用匿名用户 no_anon_passwordYES #匿名用户login时不询问口令 anon_upload_enableyes | no # 匿名用户对文件(非目录)上传权限。 anon_world_readable_onlyyes | …...
遥感数据获取、处理、分析到模型搭建全流程学习!DeepSeek、Python、OpenCV驱动空天地遥感数据分析
【扔进数据,直接出结果】在科技飞速发展的时代,遥感数据的精准分析已经成为推动各行业智能决策的关键工具。从无人机监测农田到卫星数据支持气候研究,空天地遥感数据正以前所未有的方式为科研和商业带来深刻变革。然而,对于许多专…...
操作系统——(管程、线程、进程通信)
目录 一、管程机制 (1)管程定义 (2)特点: 二、进程通信 (1)概念 (2)高级通信机制 三、线程 (1)概念 (2)与进程比较…...
Sqlserver安全篇之_启用和禁用Named Pipes的案列介绍
https://learn.microsoft.com/zh-cn/sql/tools/configuration-manager/named-pipes-properties?viewsql-server-ver16 https://learn.microsoft.com/zh-cn/sql/tools/configuration-manager/client-protocols-named-pipes-properties-protocol-tab?viewsql-server-ver16 默认…...
Redis 本地安装
首先安装: https://redis.io/docs/latest/operate/oss_and_stack/install/install-redis/install-redis-from-source/ 进入root目录 tar -xzvf redis-stable.tar.gz cd redis-stable make然后 install sudo make install最后可以直接启动 redis-server但是此时启…...
外卖订单如何教会我变量与数据类型?
目录 前言一、现实场景1.1 你点的每一碗,都是程序员的KPI1.2 关键数据角色扮演 二、技术映射三、知识点呈现3.1 变量——你的数字日记本3.2 数据类型——数值的「职业规划」3.3 运算符——数学老师的黑板擦 四、代码实现4.1 基础版:计算器の复仇4.2 进阶…...
HOW - 平时如何保持学习和成长?
目录 前言数字时代的系统性学习方法论一、场景驱动的实战学习:从工具赋能到知识沉淀二、结构化的系统学习:构建知识体系的方法论(一)精准学习策略(二)学习成效评估体系(三)专项研究 …...
Web开发-JS应用原生代码前端数据加密CryptoJS库jsencrypt库代码混淆
知识点: 1、安全开发-原生JS-数据加密&代码混淆 2、安全开发-原生JS-数据解密安全案例 一、演示案例-WEB开发-原生JS&第三方库-数据加密 前端技术JS实现: 1、非加密数据大致流程: 客户端发送->明文数据传输-服务端接受数据->…...
手动集成sqlite的方法
注意到sqlite有backup方法(https://www.sqlite.org/backup.html)。 也注意到android中sysroot下,没有sqlite3的库,也没有相关头文件。 如果要使用 sqlite 的backup,那么就需要手动集成sqlite代码到项目中。可以如下操…...
比特币牛市还在不在
在加密货币的风云世界里,比特币的一举一动始终牵动着投资者们的神经。近期比特币的涨幅动作,再次引发了市场对于牛市是否仍在延续的激烈讨论。 在深入探索比特币市场的过程中,获取全面且及时的资讯至关重要。您可以通过访问Techub News&#…...
Python、MATLAB和PPT完成数学建模竞赛中的地图绘制
参加数学建模比赛时,很多题目——诸如统计类、数据挖掘类、环保类、建议类的题目总会涉及到地理相关的情景,往往要求我们制作与地图相关的可视化内容。如下图,这是21年亚太赛的那道塞罕坝的题目,期间涉及到温度、降水和森林覆盖率…...
跨平台RTSP高性能实时播放器实现思路
跨平台RTSP高性能实时播放器实现思路 目标:局域网100ms以内超低延迟 一、引言 现有播放器(如VLC)在RTSP实时播放场景中面临高延迟(通常数秒)和资源占用大的问题。本文提出一种跨平台解决方案,通过网络层…...
编写一个简单的chrome截图扩展
文件结构: screenshot |-- background.js ---> service_worker运行的js |-- images ---> 图片 | |-- logo-128x128.png | |-- logo-16x16.png | |-- logo-32x32.png | -- logo-48x48.png -- manifest.json --->…...
吴恩达机器学习笔记复盘(六)梯度下降算法
简介 梯度下降(Gradient Descent)是一种常用的优化算法,广泛应用于机器学习、深度学习等领域,在这里是用于求J(w,b)局部最小值。 我自己觉得这样说有点过于抽象。换个直观点的说法就是,一个人…...
【机器学习chp14 — 3】生成式模型—生成对抗网络GAN(超详细分析,易于理解,推导严谨,一文就够了)
目录 三、生成对抗网络 ( Generative Adversarial Networks,GAN ) 1、GAN的基本思想 (1)生成器与判别器的基本结构与演变 (2)“对抗”机制及名词由来 2、GAN训练的基本算法 (1)网络初始化与…...
机器人打磨控制技术
工具姿态调整运动 法线方向对齐运动:机器人实时调整工具姿态,使打磨工具的轴线与工件曲面的法线方向一致。例如,在球面打磨时,工具需始终垂直于球面切线。角度补偿运动:针对倾斜或不规则曲面,通过调整机器人…...
K8S学习之基础四十:K8S配置altermanager发送告警到钉钉群
配置altermanager发送告警到钉钉群 创建钉钉群,设置机器人助手(必须是管理员才能设置),获取webhook webhook: https://oapi.dingtalk.com/robot/send?access_token25bed933a52d69f192347b5be4b2193bc0b257a6d9ae68d81619e3ae3d93f7c6…...
Spring Boot + Spring Integration整合MQTT打造双向通信客户端
1. 概述 本文分两个章节讲解MQTT相关的知识,第一部份主要讲解MQTT的原理和相关配置,第二个章节主要讲和Spring boot的integration相结合代码的具体实现,如果想快速实现功能,可直接跳过第一章节查看第二章讲。 1.1 MQTT搭建 为了…...
Sampling – Model Context Protocol Specification
网页链接 https://spec.modelcontextprotocol.io/specification/draft/client/sampling/ 主要内容概述 该网页详细介绍了Model Context Protocol (MCP) 中的“Sampling”功能。Sampling允许服务器通过客户端请求语言模型(LLM)生成文本、音频或图像内容…...
Java 填充 PDF 模版
制作 PDF 模版 安装 OnlyOffice 从 OnlyOffice 官网下载 OnlyOffice Desktop,安装过程很简单,一路下一步即可。用 OnlyOffice 制作 PDF 模版(表单) 使用 OnlyOffice 表单设计器,制作表单,如下图 注意命名…...
前端项目中应该如何选择正确的图片格式
在前端项目中选择正确的图片格式是优化页面性能、提升用户体验的关键步骤之一。以下是常见图片格式的特点、适用场景及选择建议,帮助你在不同场景下做出最优决策: 一、常见图片格式对比 格式特点适用场景不适用场景JPEG- 有损压缩,文件小- 不…...
Vulnhub-dedecms织梦通关攻略
姿势一、通过文件管理器上传WebShell 第一步:进入后台,找到文件管理器上传木马文件 第二步:使用蚁剑进行连接 #文件地址 http://localhost/dedecms/shell.php 姿势二、修改模板⽂件拿WebShell 第一步:修改模板文件,删除…...
数据集获取
sklearn数据集 sklearn有四部分数据。其中sklearn的数据集有两部分真实的数据,一部分嵌入到了sklearn库中,即安装好sklearn后就自带了一部分数据,这些数据的规模比较小称为small toy datasets ,还有一部分数据是需要在网上下载的,sklearn提供了下载的api接口,这些数据规…...
