代码随想录算法训练营第60期第五十五天打卡

article/2025/7/1 23:00:08

        大家好,我们今天继续我们图论的部分,其实我们昨天是主要讲解了深搜与广搜的理论基础,我们大体上了解了两种算法的差异与适用情景,今天我们就继续我们的图论的章节,以后几天的题目是图论中比较有名的问题叫做岛屿问题,我们就开始今天的题目。

第一题对应卡码网编号为99的题目岛屿数量

       这是我们岛屿问题里面的第一题,我们是需要求岛屿的数量,我们还是先来看一下这道题目的题目要求:

        大家看我们题目给出的地图就可以了解什么样的陆地才可以叫做岛屿,首先要是水平方向或者垂直方向上相邻,但注意斜方向的不算,就比如说我们题目给出的地图很明显左上方的可以是一个岛屿,右下方的也可以是岛屿,当然中间由于跟两个岛屿是斜着连接的所以只能单独算作一个岛屿,因此我们这道题也是很适合使用深搜来解决,我们就搜索四个方向,当然要保证当前的节点没有被访问过,一个节点肯定只能属于一个岛屿,总不能一个节点既属于一个岛屿又属于另一个岛屿,还有一点大家需要注意我们搜索的过程中千万不可以超出地图的边界,因此我们可以尝试写出深搜的代码:

#include <iostream>
#include <vector>
using namespace std;
int dir[4][2] = {0, 1, 1, 0, 0, -1, -1, 0};//方向数组表示上下左右四个方向
void dfs(const vector<vector<int>>&grid,vector<vector<bool>>&visited,int x,int y)
{for (int i = 0; i < 4; ++i){//这个其实是关键我们这样就可以表示所有的方向int nextx = x + dir[i][0]; int nexty = y + dir[i][1];//越界的情况要排除掉if (nextx < 0 || nextx >= grid.size() || nexty < 0 || nexty >= grid[0].size()) continue;//如果当前节点没有被访问过的话并且是陆地我们就可以继续搜索if (!visited[nextx][nexty] && grid[nextx][nexty]){visited[nextx][nexty] = true;dfs(grid, visited, nextx, nexty);}}return;
}
int main()
{int n, m; cin >> n >> m;vector<vector<int>> grid(n + 1, vector<int>(m + 1, 0));vector<vector<bool>> visited(n + 1, vector<bool>(m + 1, 0));for (int i = 0; i < n; ++i){for (int j = 0; j < m; ++j) cin >> grid[i][j];}int count = 0;for (int i = 0; i < n; ++i){for (int j = 0; j < m; ++j) {if (!visited[i][j] && grid[i][j]){visited[i][j] = true;count++;dfs(grid, visited, i, j);}}}cout << count << '\n';return 0;
}

        当然上面是深搜的写法,那这道题目可以使用广搜的写法吗?是可以的,我们依旧可以通过广搜的写法来解决这道题目,只要 加入队列就代表 走过,就需要标记,而不是从队列拿出来的时候再去标记走过。这个要注意我们广搜非常重要的点,我们广搜是借助队列来搜索的,我们只要加入队列就立马标记,这就表示我们已经访问过了这个陆地,那这样的话根据我们广搜的模板与对题目的理解我们就可以尝试给出广搜的代码:

#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>>&grid,vector<vector<bool>>&visited,int x,int y)
{//定义队列queue<pair<int, int>> que;//将起点添加到队列里面que.push({x, y});visited[x][y] = true; //只要加入队列立刻标记while(!que.empty()){pair<int, int> cur = que.front(); que.pop();int curx = cur.first;int cury = cur.second;for (int i = 0; i < 4; ++i){int nextx = curx + dir[i][0];int nexty = cury + dir[i][1];if (nextx < 0 || nextx >= grid.size() || nexty < 0 || nexty>=grid[0].size()) continue; //超出边界的部分去掉if (!visited[nextx][nexty] && grid[nextx][nexty]){que.push({nextx,nexty});visited[nextx][nexty] = true;}}}
}int main()
{int n,m; cin >> n >> m;vector<vector<int>> grid(n + 1, vector<int>(m + 1, 0));vector<vector<bool>> visited(n + 1, vector<bool>(m + 1, false));for (int i = 0; i < n; ++i){for (int j = 0; j < m; ++j) cin >> grid[i][j];}//存储岛屿的数量int result = 0;for (int i = 0; i < n; ++i){for (int j = 0; j < m; ++j){if (!visited[i][j] && grid[i][j]){result++;bfs(grid, visited, i, j);}}}cout << result << '\n';return 0;
}

       这个是广搜的代码,其实跟我们上次的广搜模板是一样的,以后的题目我主要只给深搜的代码,我尽力也给广搜的代码,我个人的话还是深搜用的多一些,请大家见谅!

第二题对应卡码网编号为100的题目岛屿的最大面积

        这是我们今天的第二题,我们这道题目其实跟上一道题的思路是很相似的,不过是上一道题目要求我们去找岛屿的数量而这道题则是求最大岛屿的面积,其实这道题我还是使用深搜来解决,我们其实就是不断更新岛屿面积不就可以了,其实不算难,前提是大家掌握清楚上一道题目的思路,我们还是使用深度优先搜索来给大家解决这道题目:

#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>> &grid, vector<vector<bool>> &visited, int x, int y)
{for (int i = 0; i < 4; ++i){int nextx = x + dir[i][0];int nexty = y + dir[i][1];if (nextx < 0 || nextx >= grid.size() || nexty < 0 || nexty >= grid[0].size()) continue;if (!visited[nextx][nexty] && grid[nextx][nexty]){count++;visited[nextx][nexty] = true;dfs(grid, visited, nextx, nexty);}}
}int main()
{int n, m; cin >> n >> m;vector<vector<int>> grid(n + 1,vector<int>(m + 1, 0));vector<vector<bool>> visited(n + 1,vector<bool>(m + 1, false));for (int i = 0; i < n; ++i){for (int j = 0; j < m; ++j) cin >> grid[i][j];}int result = 0;for (int i = 0; i < n; ++i){for (int j = 0; j < m; ++j){if (!visited[i][j] && grid[i][j]){count = 1;//最小的岛屿面积其实就是1也就是孤岛visited[i][j] = true;dfs(grid, visited, i, j);//大家注意我们这里的dfs其实不仅仅找到了岛屿而且还把岛屿面积计算出来了result = max(result, count);//不断更新岛屿的面绩}}}cout << result << '\n';return 0;
}

         当然本题的一些细节我们不可忽略,比如我们搜索的位置不能超出地图的边界,我们还要注意使用一个变量来存储所在的岛屿的面积,大家想明白这一些估计本题目就很简单了。那其实本题目使用广搜也是可以的,我们就需要使用一个队列,我可以给出广搜的代码:

class Solution {
private:int count;int dir[4][2] = {0, 1, 1, 0, -1, 0, 0, -1}; // 四个方向void bfs(vector<vector<int>>& grid, vector<vector<bool>>& visited, int x, int y) {queue<int> que;que.push(x);que.push(y);visited[x][y] = true; // 加入队列就意味节点是陆地可到达的点count++;while(!que.empty()) {int xx = que.front();que.pop();int yy = que.front();que.pop();for (int i = 0 ;i < 4; i++) {int nextx = xx + dir[i][0];int nexty = yy + dir[i][1];if (nextx < 0 || nextx >= grid.size() || nexty < 0 || nexty >= grid[0].size()) continue; // 越界if (!visited[nextx][nexty] && grid[nextx][nexty] == 1) { // 节点没有被访问过且是陆地visited[nextx][nexty] = true;count++;que.push(nextx);que.push(nexty);}}}}public:int maxAreaOfIsland(vector<vector<int>>& grid) {int n = grid.size(), m = grid[0].size();vector<vector<bool>> visited = vector<vector<bool>>(n, vector<bool>(m, false));int result = 0;for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {if (!visited[i][j] && grid[i][j] == 1) {count = 0;bfs(grid, visited, i, j); // 将与其链接的陆地都标记上 trueresult = max(result, count);}}}return result;}
};

        其实这道题目比较简单,我们的深搜与广搜都可以实现,大家注意理解就可以,我们这道题就分享到这里。

今日总结

        今天我们开始接触了一些岛屿问题,其实我们发现大多都不算难,我们前提是需要掌握好深度优先搜索与广度优先搜索,理解好题意就不难了,比如说今天的这道岛屿的最大面积的题目其实只要理解好前面岛屿的数量的问题就很简单了,我们今天的分享就到这里,我们下一次博客再见!


http://www.hkcw.cn/article/qWSSyUIBem.shtml

相关文章

【音视频】FFmpeg 编码H265

一、概述 实现了读入本地yuv文件&#xff0c;通过libx265编码为H265格式&#xff0c;并存储到本地文件中 二、实现流程 准备文件 在build路径下准备yuv文件 在项目中添加文件参数&#xff0c;输出为h265文件&#xff0c;使用libx265编码 初始化解码器 通过传进来的libx265…

贪心算法应用:带权任务间隔调度问题详解

贪心算法应用&#xff1a;带权任务间隔调度问题详解 贪心算法是一种在每一步选择中都采取在当前状态下最好或最优&#xff08;即最有利&#xff09;的选择&#xff0c;从而希望导致结果是全局最好或最优的算法。带权任务间隔调度问题是贪心算法的一个经典应用场景。 问题定义…

Git-flow流

Git git是版本控制软件&#xff0c;一般用来做代码版本控制 github是一个免费版本控制仓库是国内外很多开源项目的集中地&#xff0c;其本体是一个git服务器 Git初始化操作 git init 初始化仓库 git status 查看当前仓库的状态 git add . 将改动的文件加到暂存区 gi…

LeetCode-链表操作题目

虚拟头指针&#xff0c;在当前head的前面建立一个虚拟头指针&#xff0c;然后哪怕当前的head的val等于提供的val也能进行统一操作 203移除链表元素简单题 /*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode(…

mybatisplus的总结

一.通用Mapper 1.首先创建一个接口与实体类 Data TableName("user") public class User { TableId(value "id", type IdType.AUTO) private Long id; TableField("name") private String name; TableField("age") pri…

UE5 创建2D角色帧动画学习笔记

UE5 创建2D角色帧动画 1.对导入的角色所有帧动画图片Apply paper2d Texture Setting 2.创建图片精灵 Create Sprite 3.全选创建的图片精灵&#xff0c;右键点击 Create Flipbook(创建图像序列视图) 4.双击此paper Flipbook 即可预览该角色帧动画 UE5 2D角色帧动画 Frames P…

MyBatisPlus--条件构造器及自定义SQL详解

条件构造器 在前面学习快速入门的时候&#xff0c;练习的增删改查都是基于id去执行的&#xff0c;但是在实际开发业务中&#xff0c;增删改查的条件往往是比较复杂的&#xff0c;因此MyBatisPlus就提供了一个条件构造器来帮助构造复杂的条件。 MyBatisPlus支持各种复杂的wher…

《类和对象--继承》

引言&#xff1a; 在刚接触C的时候&#xff0c;我们首先学习了有关类和对象的一些基础知识&#xff0c;今天我们就要接着学习类和对象的另一板块–继承。 一&#xff1a;继承的概念和定义 1. 继承的概念 继承(inheritance)机制是面向对象程序设计使代码可以复用的最重要的手…

利用R语言生成区试中随机区组试验设计——多点

目前&#xff0c;区试要求对照不得位于区组的首尾小区&#xff0c;且不同区组的相邻小区位置不得出现同一品种。基于这一要求&#xff0c;编写了R语言的随机区组试验设计。此函数可用于多个试验点试验设计生成情况。 rcbd函数有6个参数&#xff1a; local_name为试验点名称的向…

pytorch基本运算-范数

引言 前序学习进程中&#xff0c;已经对pytorch基本运算有了详细探索&#xff0c;文章链接有&#xff1a; 基本运算 广播失效 乘除法和幂运算 hadamard积、点积和矩阵乘法 上述计算都是以pytorch张量为运算元素&#xff0c;这些张量基本上也集中在一维向量和二维矩阵&#x…

STM32G4 电机外设篇(四)DAC输出电流波形 + CAN通讯

目录 一、STM32G4 电机外设篇&#xff08;四&#xff09;DAC输出电流波形 CAN通讯1 DAC输出电流波形1.1 STM32CubeMX配置和Keil代码1.2 实验现象 2 CAN/CANFD通讯2.1 STM32CubeMX配置和Keil代码2.2 实验现象 附学习参考网址欢迎大家有问题评论交流 (* ^ ω ^) 一、STM32G4 电机…

电子电气架构 --- 后轮转向的一点事情

我是穿拖鞋的汉子&#xff0c;魔都中坚持长期主义的汽车电子工程师。 老规矩&#xff0c;分享一段喜欢的文字&#xff0c;避免自己成为高知识低文化的工程师&#xff1a; 做到欲望极简&#xff0c;了解自己的真实欲望&#xff0c;不受外在潮流的影响&#xff0c;不盲从&#x…

web复习(四)

盒子模型的例题 例一&#xff1a; <!doctype html> <html> <head> <meta charset"utf-8"> <title>咖啡店banner</title> <style type"text/css"> /*将页面中所有元素的内外边距设置为0*/ *{ padding:0; margin…

Cesium添加点线面(贴地)

// 创建一个图元集合const primitives viewer.scene.primitives.add(new Cesium.PrimitiveCollection());1、点上图 // 定义点的位置&#xff08;中国不同城市的经纬度&#xff09;const points [{ lon: 116.4074, lat: 39.9042, name: "北京" },{ lon: 121.4737, …

技术文档:MD520系列变频器配套杭州干扰净GRJ9000S系列EMC电源滤波器安装指南

1. 引言 MD520系列通用变频器是汇川技术有限公司&#xff08;Inovance&#xff09;设计的高性能电流矢量控制交流驱动器&#xff0c;广泛应用于纺织、造纸、机床、包装、食品、风机和水泵等行业。为确保其在复杂电磁环境中稳定运行并不对其他设备造成干扰&#xff0c;手册推荐…

【基于阿里云搭建数据仓库(离线)】DataWorks中删除节点

1.右击想要删除的节点&#xff0c;点击删除 2. 显示如下界面&#xff0c;点击“去下线” 3.进入到如下界面&#xff0c;点击红色框出来的 4.重新右击想要删除的目标节点&#xff0c;点击删除 5. 点击去下线 6.点击开始下线 7.点击“确认发布” 8.点击“确认” 9.点击“重新删除…

【GESP真题解析】第 6 集 GESP 三级 2023 年 9 月编程题 1:小杨的储蓄

大家好,我是莫小特。 这篇文章给大家分享 GESP 三级 2023 年 9 月编程题第 1 题:小杨的储蓄。 题目链接 洛谷链接:B3867 小杨的储蓄 一、完成输入 根据输入格式的描述,输入有两行,第一行为两个整数 N 和 D,数据范围: 1 ≤ N ≤ 1000 1\le N \le 1000 1≤N≤1000, 1 …

MySQL-多表关系、多表查询

一. 一对多(多对一) 1. 例如&#xff1b;一个部门下有多个员工 在数据库表中多的一方(员工表)、添加字段&#xff0c;来关联一的一方(部门表)的主键 二. 外键约束 1.如将部门表的部门直接删除&#xff0c;然而员工表还存在其部门下的员工&#xff0c;出现了数据的不一致问题&am…

Arbitrum Stylus 合约实战 :Rust 实现 ERC721

在上一篇中&#xff0c;我们学习了如何在 stylus 使用 rust 编写 ERC20合约&#xff0c;并且部署到了Arbitrum Sepolia &#xff0c;今天我们继续学习&#xff0c;如何在 stylus 中使用 rust 实现 ERC721 合约&#xff0c;OK, 直接开干&#xff01; 关于环境准备&#xff0c;请…

超声波测距三大算法实测对比

前言 声波测距的数据包含很大噪声&#xff0c;即使障碍物&#xff08;以纸板为例&#xff09;静止&#xff0c;测量距离数据也上下跳变&#xff0c;需要通过数据滤波算法降低测量误差&#xff0c;主要滤波算法有平均值滤波和卡尔曼滤波。 在超声波测距中&#xff0c;无滤波、…