算法|图论 3

LeetCode 130- 被围绕的区域

题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

题目描述:给你一个 m x n 的矩阵 board ,由若干字符 'X' 和 'O' ,找到所有被 'X' 围绕的区域,并将这些区域里所有的 'O' 用 'X' 填充。

解题思路(思路一是自己的思路,思路二题解思路,不过用两种遍历方式写出来)

思路一(深度优先遍历):

我的思路:是开辟一个二维数组,存储二元组,来记录那些下标,首先是一个一维数组,每次记录我们当前遍历岛屿的下标,当被环绕的时候压入到二维数组中,否则直接清空。类似将所有岛屿都淹没,然后再看哪些岛屿没被包围再还原成陆地。

  1. 首先确定递归函数的参数,返回值。覆盖那些被环绕的区域,我们直接设置两个全局变量vec(存储所有需要还原的海洋)和tmp(存储当前我们遍历的这片岛屿的下标),flag表示是否被包围,这样可以不用写太多参数传递。返回值就是void,参数需要图和一个x和y来记录当前在哪个岛屿。下次从这个岛屿开始走的。
  2. 确定终止条件,本题按我们的逻辑,先进入循环再判断是否应该终止,那么终止条件就是:当超出网格范围(这里还需要把flag 设置为false,表示没被包围) 或 该岛屿已经是海洋 就终止。
  3. 单层处理逻辑,每次将当前岛屿淹没(这里也就是设置为'X'),然后将其下标压入tmp(为什么有tmp,是因为我们不知道当前的这片岛屿马上是否要恢复,也就是变成'O'所以需要一个临时的,当我们确定要恢复的时候就将其压入到vec中)。
class Solution {
public:bool flag = true; //表示是否被环绕(只要相连的岛屿有一个在边界就不是被环绕的),被环绕就不用撤回修改vector<vector<pair<int,int>>> vec;//存所有岛屿下标,其中全都是要变回'O'的vector<pair<int,int>> tmp; //保存当前遍历这片岛屿的下标,一会可能填充。void dfs(vector<vector<char>> &grid,int x,int y){if(x < 0 || y < 0 || x >= grid.size() || y >= grid[0].size()){flag = false;//表示没有被环绕return ;}if(grid[x][y] == 'X') return;tmp.push_back({x,y});//压入当前岛屿的下标grid[x][y] = 'X';dfs(grid,x+1,y);dfs(grid,x-1,y);dfs(grid,x,y+1);dfs(grid,x,y-1);}void solve(vector<vector<char>>& grid) {int m = grid.size(),n = grid[0].size();for(int i=0;i<m;i++){for(int j=0;j<n;j++){if(grid[i][j] == 'O'){dfs(grid,i,j);//当flag为false,也就是岛屿没有被包围,我们就将其压入vec中,最后再还原if(flag == false){vec.push_back(tmp);tmp.clear();//这里注意要把tmp清空了,方便下次使用flag = true;//flag再改为默认值}else{//这里不改flag是因为如果走这个分支,那flag一定还是默认值truetmp.clear();}}}}//将未被包围的小岛屿还原为'O'for(int i=0;i<vec.size();i++){for(int j=0;j<vec[i].size();j++){grid[vec[i][j].first][vec[i][j].second] = 'O';}}return ;}
};

思路二(广度优先遍历):

比较猛的一个思路:本题我们可以看到,只有和边界相连的O不会变,其余的都得变成X,那么我们可以将与边界相连的所有O全部变成一个特定符号如'-',这样,其中所有的'-'都是与边界相连的,马上会再变成'O'。而这个时候图中所有的'O'都是被包围的,全都变为'X'即可。

class Solution {
public:int dir[4][2] = {0,1,1,0,-1,0,0,-1};void bfs(vector<vector<char>> &grid,int x,int y){queue<pair<int,int>> que;que.push({x,y});grid[x][y] = '-';//将与边界相连的全部变为'-'//广度优先遍历while(!que.empty()){pair<int,int> cur = que.front();que.pop();for(int i=0;i<4;i++){int nextx = cur.first + dir[i][0];int nexty = cur.second + dir[i][1];if(nextx < 0 || nexty < 0 || nextx >= grid.size() || nexty >= grid[0].size() ||grid[nextx][nexty] != 'O') continue;que.push({nextx,nexty});grid[nextx][nexty] = '-';}}}void solve(vector<vector<char>>& grid) {int row = grid.size(),col = grid[0].size();for(int i=0;i<col;i++){//遍历第一行的所有列if(grid[0][i] == 'O') bfs(grid,0,i);//遍历最后一行的所有列if(grid[row-1][i] == 'O') bfs(grid,row-1,i);}for(int i=0;i<row;i++){//遍历第一列的所有行if(grid[i][0] == 'O') bfs(grid,i,0);//遍历最后一列的所有行if(grid[i][col-1] == 'O') bfs(grid,i,col-1);}//这个时候图中所有'-'都是与边界相连的,所有'O'都是被包围起来的。for(int i=0;i<row;i++){for(int j=0;j<col;j++){//这俩式子顺序反了,导致花了我半小时调试if(grid[i][j] == 'O')grid[i][j] = 'X';if(grid[i][j] == '-')grid[i][j] = 'O';}}return ;}
};

总结:

  • 深搜和广搜的问题,广搜里面写的那个思路很清奇,还是得多看题目的提示,可以减少一点时间和空间的损耗。

LeetCode 417- 太平洋大西洋水流问题

题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

题目描述:有一个 m × n 的矩形岛屿,与 太平洋大西洋 相邻。 “太平洋” 处于大陆的左边界和上边界,而 “大西洋” 处于大陆的右边界和下边界。

这个岛被分割成一个由若干方形单元格组成的网格。给定一个 m x n 的整数矩阵 heights , heights[r][c] 表示坐标 (r, c) 上单元格 高于海平面的高度

岛上雨水较多,如果相邻单元格的高度 小于或等于 当前单元格的高度,雨水可以直接向北、南、东、西流向相邻单元格。水可以从海洋附近的任何单元格流入海洋。

返回网格坐标 result 的 2D 列表 ,其中 result[i] = [ri, ci] 表示雨水从单元格 (ri, ci) 流动 既可流向太平洋也可流向大西洋

解题思路

首先明确本题题意,意思就是雨水高的地方能往雨水低的地方流,要我们求出能流向两大洋的点坐标。

思路一(深度优先遍历):

这题总体思路就是遍历边界点(也就是能直接流进大洋的点),再逆流遍历,因为雨水往低处流,我们逆流遍历就可以找到所有大于边界的雨水高度的点,这些点就是可以直接流进大洋的点

  1. 首先确定递归函数的参数,返回值。参数我们需要设置一个isvisited来表示这个点能不能走到其中一个大洋中去。还有x,y坐标来表示当前遍历到的点的位置
  2. 确定终止条件,本题按我们的逻辑,先进入循环再判断是否应该终止,那么终止条件就是:当超出网格范围 当前遍历的是海洋 就跳过。不过这里需要注意,这道题目我们这里的逻辑是逆流而上,所以下一次要去的节点的雨水高度 小于 我们当前节点的雨水高度的时候也直接跳过。
  1. 单层处理逻辑,每次进入递归,我们就将访问设置为true,代表可以直接流进大洋。不过在处理遍历的时候有点麻烦,需要注意m和n各表示的是什么,别弄混了。
class Solution {
private:int dir[4][2] = {-1, 0, 0, -1, 1, 0, 0, 1}; // 保存四个方向// 从低向高遍历,注意这里visited是引用,即可以改变传入的pacific和atlantic的值void dfs(vector<vector<int>>& heights, vector<vector<bool>>& visited, int x, int y) {if (visited[x][y]) return;visited[x][y] = true;for (int i = 0; i < 4; i++) { // 向四个方向遍历int nextx = x + dir[i][0];int nexty = y + dir[i][1];// 超过边界if (nextx < 0 || nextx >= heights.size() || nexty < 0 || nexty >= heights[0].size()) continue;// 高度不合适,注意这里是从低向高判断if (heights[x][y] > heights[nextx][nexty]) continue;dfs (heights, visited, nextx, nexty);}return;}
public:vector<vector<int>> pacificAtlantic(vector<vector<int>>& heights) {vector<vector<int>> result;int n = heights.size();int m = heights[0].size(); // 这里不用担心空指针,题目要求说了长宽都大于1// 记录从太平洋边出发,可以遍历的节点vector<vector<bool>> pacific = vector<vector<bool>>(n, vector<bool>(m, false));// 记录从大西洋出发,可以遍历的节点vector<vector<bool>> atlantic = vector<vector<bool>>(n, vector<bool>(m, false));// 从最上最下行的节点出发,向高处遍历for (int i = 0; i < n; i++) {dfs (heights, pacific, i, 0); // 遍历最上行,接触太平洋dfs (heights, atlantic, i, m - 1); // 遍历最下行,接触大西洋}// 从最左最右列的节点出发,向高处遍历for (int j = 0; j < m; j++) {dfs (heights, pacific, 0, j); // 遍历最左列,接触太平洋dfs (heights, atlantic, n - 1, j); // 遍历最右列,接触大西洋}for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {// 如果这个节点,从太平洋和大西洋出发都遍历过,就是结果if (pacific[i][j] && atlantic[i][j]) result.push_back({i, j});}}return result;}
};

总结:

  • 逆流而上的操作,主要是根据边界来想到了这个思路。

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

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

相关文章

一键集成prometheus监控微服务接口平均响应时长

一、效果展示 二、环境准备 prometheus + grafana环境 参考博文:https://blog.csdn.net/luckywuxn/article/details/129475991 三、导入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter

UE5学习笔记(1)——从源码开始编译安装UE5

目录 0. 前期准备1. Git bash here2. 克隆官方源码。3. 选择安装分支4. 运行Setup.bat&#xff0c;下载依赖文件5. 运行GenerateProjectFiles.bat生成工程文件6. 生成完成&#xff0c;找到UE5.sln/UE4.sln7. 大功告成 0. 前期准备 0.1 在windows的话&#xff0c;建议装一个Git…

Markdown(MD)——Typora Markdown安装教程(2023九月亲测可用!!!)

目录 一、简介 1.Markdown简介 2.Markdown特点 3.Typora简介 二、安装教程 1.下载安装包 2.解压到文件夹 3.安装 4.破解 ​编辑5.激活 三、Markdown常用语法 1.常用语法 2.用于编辑LaTex公式 四、其他编辑器 一、简介 1.Markdown简介 Markdown 是一种轻量级标记语…

WPF——Control与Template理解

文章目录 一、前言二、控件三、模板3.1 DataTemplate3.2 ControlTemplate3.3 ContentPresenter 四、结语 一、前言 最近又翻看了下刘铁猛的《深入浅出WPF》&#xff0c;发现对模板章节中的部分内容有了更深的体会&#xff0c;所以写篇文扯扯。 文章标题是Control与Template&a…

企业级数据仓库-理论知识

D3 AM 大数据中间件 Hive&#xff1a;将SQL转化成分布式Map/Reduce进行运算&#xff0c;也支持转换成Spark,需要单独安装Hive集群才能访问Spark,支持60%的SQL&#xff0c;延迟比较大。SparkSQL:属于Spark生态圈&#xff0c;Hive on Sqark。HBase: NoSQL,高并发读&#xff0c;适…

c语言进阶部分详解(指针进阶1)

大家好&#xff01;指针的初阶内容我已经写好&#xff0c;可移步至我的文章&#xff1a;c语言进阶部分详解&#xff08;指针初阶&#xff09;_总之就是非常唔姆的博客-CSDN博客 基本内容我便不再赘述&#xff0c;直接带大家进入进阶内容&#xff1a; 目录 一.字符指针 1.讲解…

那些年我们遇到过的关于excel的操作

本文为直接从百度上搜索的关于excel的函数使用&#xff0c;方便以后用&#xff0c;希望会持续补充 excel中筛选出两列重复的数据【场景&#xff1a;A、B两列数据个数不同且无序&#xff0c;想找出A列中的数据在B列中不存在的&#xff0c;通过比较后单元格为空的代表该行不存在的…

Mac 安装软件各种报错解决方案

Mac 安装软件各种报错解决方案 文章目录 Mac 安装软件各种报错解决方案一. 打开允许“允许任何来源”二. 无法打开"xxx"&#xff0c;因为它不是从App Store下载三. 无法打开"xxx"&#xff0c;因为 Apple无法检查其是否包含恶意软件。四. "xxx"已…

【入门篇】ClickHouse最优秀的开源列式存储数据库

文章目录 一、什么是ClickHouse&#xff1f;OLAP场景的关键特征列式数据库更适合OLAP场景的原因输入/输出CPU 1.1 ClickHouse的定义与发展历程1.2 ClickHouse的版本介绍 二、ClickHouse的主要特性2.1 高性能的列式存储2.2 实时的分析查询2.3 高度可扩展性2.4 数据压缩2.5 SQL支…

C语言——通讯录管理系统

通讯录管理系统项目简介 功能说明 控制台黑窗口实现程序需要满足以下几个功能 程序开始运行时首先显示选择菜单界面&#xff0c;根据用户输入确定实现何种功能 程序界面 代码实现 多文件实现 和之前写的实战项目类似&#xff0c;这里同样采用多文件实现的方式 多文件写代码…

各种电机驱动原理

步进电机 步进电机参考资料 野火官方文档 步进电机驱动原理 上面参考文档中有的内容就不写了&#xff0c;写一下我自己的总结吧。 说明&#xff1a; 电机驱动器输入信号有电机转动方向信号DIR&#xff0c;电机转速信号PWM&#xff0c;电机使能信号EN&#xff1b;电机驱动器…

S7-1200PLC和LED电子看板通信(TCP/IP)

S7-200SMART PLC和LED电子看板通信应用,请查看下面文章链接: SMART 200 PLC UDP通讯应用LED看板_RXXW_Dor的博客-CSDN博客开放式用户通信 (OUC) 库:数据解析:https://rxxw-control.blog.csdn.net/article/details/121424897这篇博客我们主要介绍S7-1200PLC和LED电子看板通…

servlet 引用src目录下子目录的class文件方法

1、MyServlet class文件所处的目录结构如下&#xff1a; 2、如果在url里直接引用是不行的&#xff0c;http://localhost:9092/GetRequest_Web_exploded/MyServlet 3、需要在web.xml映射后才行&#xff1a; MyServlet com.example.MyServlet <servlet-mapping><ser…

HI_NAS linux 记录

dev/root 100% 占用解决记录 通过下面的命令查看各文件夹 大小 sudo du --max-depth1 -h # 统计当前文件夹下各个文件夹的大小显示为M 最终发现Var/log 占用很大空间 发现下面两个 log 占用空间很大&#xff0c;直接 rm-rf 即可 HI NAS python3 记录 # 安装pip3 sudo apt u…

Linux下C语言使用 netlink sockets与内核模块通信

netlink简介 Netlink套接字是用以实现用户进程与内核进程通信的一种特殊的进程间通信(IPC) ,也是网络应用程序与内核通信的最常用的接口。在Linux标准内核中&#xff0c;系统默认集成了很多netlink实例&#xff0c;比如日志上报、路由系统等&#xff0c;netlink消息是双向的&a…

Knife4j系列--使用方法

原文网址&#xff1a;Knife4j系列--使用/教程/实例/配置_IT利刃出鞘的博客-CSDN博客

python LeetCode 刷题记录 58

题目 给你一个字符串 s&#xff0c;由若干单词组成&#xff0c;单词前后用一些空格字符隔开。返回字符串中 最后一个 单词的长度。 单词 是指仅由字母组成、不包含任何空格字符的最大子字符串。 示例 输入&#xff1a;s "Hello World" 输出&#xff1a;5 解释&am…

Linux中如何获取输入设备(如触摸屏、按键等)的事件信息

Linux中如何获取输入设备&#xff08;如触摸屏、按键等&#xff09;的事件信息 在Linux中&#xff0c;可以使用getevent命令来获取输入设备&#xff08;如触摸屏、按键等&#xff09;的事件信息。如果你想在C程序中获取输入设备事件&#xff0c;可以使用以下步骤&#xff1a; …

【golang】调度系列之P

调度系列 调度系列之goroutine 调度系列之m 在前面两篇中&#xff0c;分别介绍了G和M&#xff0c;当然介绍的不够全面&#xff08;在写后面的文章时我也在不断地完善前面的文章&#xff0c;后面可能也会有更加汇总的文章来统筹介绍GMP&#xff09;。但是&#xff0c;抛开技术细…

代码随想录算法训练营19期第56天

583. 两个字符串的删除操作 代码随想录 初步思路&#xff1a;动态规划。 总结&#xff1a; 【1】第一步先求出两个字符串的最长公共子序列长度。 【2】删除的最少步数 两个字符串的总长度减去两个最长公共子序列的长度。 用时&#xff1a;45分钟 72. 编辑距离 代码随…