LeetCode130:被围绕的区域(图的简化版之网格结构上的DFS)

题目

在这里插入图片描述
注意:
1 <= m, n <= 200
board[i][j] 为 ‘X’ 或 ‘O’

思路

根据一般网格结构上的DFS,或者说岛屿问题,第一反应很容易想到找出所有的‘O’然后开始DFS遍历,改为‘X’。

但是这里有个联通的问题,如果这个‘O’是边界上的‘O’或者与边界上的‘O’联通,那么它实际上不应该被改为‘X’。

为此我们应该先预处理,从边界上的‘O’出发进行DFS遍历,找出所有与其相连的‘O’,这个过程中为了保证DFS不陷入死循环,我们要将遍历过的‘O’改掉,但是不能改为‘X’,因为最后我们是要把这些‘O’再复原回去的,如果我们改为了‘X’,之后就无法找出具体哪些节点要复原了,所以这里用另外的字母‘N’代替。

预处理后还剩下的‘O’则是与边界的‘O’不连通的点了,我们正常DFS遍历并改为‘X’。

最后则是将所有的‘N’再改回‘O’。

代码

初版代码

class Solution {public void solve(char[][] board) {int m = board.length;int n = board[0].length;//1.预处理边界的O,让其等于N,且从其dfs遍历的点都变为Nfor(int r = 0;r<m;r++){if(board[r][0]=='O') {dfs(board,r,0,'N');}if(board[r][n-1]=='O') {dfs(board,r,n-1,'N');}}for(int c=0;c<n;c++){if(board[0][c]=='O') {dfs(board,0,c,'N');}if(board[m-1][c]=='O') {dfs(board,m-1,c,'N');}}//2.遍历剩下所有的O,从其开始出发dfs遍历for(int r=0;r<m;r++){for(int c=0;c<n;c++){if(board[r][c]=='O')dfs(board,r,c,'X');}}//3.将所有的N换回O。for(int r=0;r<m;r++){for(int c=0;c<n;c++){if(board[r][c]=='N')board[r][c]='O';}}}public void dfs(char[][] board, int r,int c,char type){//为了让边界的O的dfs和不与边界O联通的O的dfs都用同一个函数,这里多加了一个参数type,如果传入的是N,那么说明是前者的dfs,最后点要改为N。如果传入的是X,说明是后者的dfs。最后点要改为X。//判断边界情况if(!ifCouldVis(board,r,c)) return;board[r][c]=type;dfs(board,r+1,c,type);dfs(board,r,c+1,type);dfs(board,r-1,c,type);dfs(board,r,c-1,type);}public boolean ifCouldVis(char[][] board,int r,int c){return r>=0 && c>=0 && r<board.length && c<board[0].length && board[r][c]=='O';}
}

4ms,击败17.92%使用 Java 的用户。说明还需要优化。

第二版代码

根据思路发现第一版代码存在三步。

  1. 找出所有边界上的O,用DFS找出与其联通的O点,将其改为N
  2. 找出剩下的所有O,用DFS找出与其联通的O点,将其改为X
  3. 还原所有的N为O

我们发现第二步的DFS是多余的,因为我们只需要把剩下所有的O改为X即可,不需要找出与其联通的O点。那么第二步的代码应该由

//2.遍历剩下所有的O,从其开始出发dfs遍历for(int r=0;r<m;r++){for(int c=0;c<n;c++){if(board[r][c]=='O')dfs(board,r,c,'X');}}

变更为

 //2.遍历剩下所有的O,从其开始出发dfs遍历for(int r=0;r<m;r++){for(int c=0;c<n;c++){if(board[r][c]=='O')board[r][c]='X';}}

此时再测效率,1ms,击败99.81%使用 Java 的用户

但是既然第二步的dfs没有了,那么传入的type参数也没用了。我们也不需要第二步和第三步分别在两个循环中,直接合并为一个循环即可,因为两层for循环是从上到下,从左到右依次循环的,所以第三步改回去的‘O’不会影响到第二步的‘O’的判断·。最终代码如下:

class Solution {public void solve(char[][] board) {int m = board.length;int n = board[0].length;//1.预处理边界的O,让其等于N,且从其dfs遍历的点都变为Nfor(int r = 0;r<m;r++){if(board[r][0]=='O') {dfs(board,r,0);}if(board[r][n-1]=='O') {dfs(board,r,n-1);}}for(int c=0;c<n;c++){if(board[0][c]=='O') {dfs(board,0,c);}if(board[m-1][c]=='O') {dfs(board,m-1,c);}}//2.遍历整个网格,因为两层for循环是从上到下,从左到右依次循环的,所以由‘N’改回去的‘O’不会影响到原来不连通的‘O’的判断·for(int r=0;r<m;r++){for(int c=0;c<n;c++){if(board[r][c]=='O') board[r][c]='X';if(board[r][c]=='N') board[r][c]='O';}}}public void dfs(char[][] board, int r,int c){//判断边界情况if(!ifCouldVis(board,r,c)) return;board[r][c]='N';dfs(board,r+1,c);dfs(board,r,c+1);dfs(board,r-1,c);dfs(board,r,c-1);}public boolean ifCouldVis(char[][] board,int r,int c){return r>=0 && c>=0 && r<board.length && c<board[0].length && board[r][c]=='O';}
}

效率没有变动,依旧是1ms,但是代码简洁了很多。

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

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

相关文章

使用easyExcel 定义表头 字体 格式 颜色等,定义表内容,合计

HeadStyle 表头样式注解 HeadFontStyle 表头字体样式 HeadStyle(fillPatternType FillPatternTypeEnum.SOLID_FOREGROUND, fillForegroundColor 22) HeadFontStyle(fontHeightInPoints 12) 以下为实现效果

华视 CVR-100UC 身份证读取 html二次开发模板

python读卡&#xff1a;python读卡 最近小唐应要求要开发一个前端的身份证读卡界面&#xff0c;结果华视CVR-100UC 的读取界面是在是有点&#xff0c;而且怎么调试连官方最基本的启动程序都执行不了。CertReader.ocx 已成功&#xff0c;后面在问询一系列前辈之后&#xff0c;大…

C++ 模板初阶【函数模板,类模板】

文章目录 泛型编程函数模板概念函数模板的格式函数模板的原理函数模板的实例化隐式实例化:让编译器根据实参推演模板参数的实际类型显式实例化&#xff1a;在函数名后的<>中指定模板参数的实际类型 函数模板的匹配规则 类模板概念类模板格式类模板的实例化 泛型编程 在我…

PCIE和USB 耦合电容放置位置记录- 一般放置在TX端

PCIE耦合电容位置 以下为引用内容&#xff0c;为记录而做的本篇文章&#xff1a; 1、PCIe标准里面明确规定&#xff1a;当两个设备通过连接器互联时&#xff0c;必须放置交流耦合电容到TX端&#xff1b; 2、放远放近最大的不同时高速信号传输中的介质损耗和趋肤效应不同&#…

MySQL:从基础到实践(简单操作实例)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 下载前言一、MySQL是什么&#xff1f;二、使用步骤1.引入库2.读入数据 提交事务查询数据获取查询结果总结 下载 点击下载提取码888999 前言 在现代信息技术的世界…

电力负荷预测 | 基于LSTM、TCN的电力负荷预测(Python)

文章目录 效果一览文章概述源码设计参考资料效果一览 文章概述 电力负荷预测 | 基于LSTM、TCN的电力负荷预测(Python) 源码设计 #------------------

相机图像质量研究(5)常见问题总结:光学结构对成像的影响--景深

系列文章目录 相机图像质量研究(1)Camera成像流程介绍 相机图像质量研究(2)ISP专用平台调优介绍 相机图像质量研究(3)图像质量测试介绍 相机图像质量研究(4)常见问题总结&#xff1a;光学结构对成像的影响--焦距 相机图像质量研究(5)常见问题总结&#xff1a;光学结构对成…

springboot项目启动报错:dynamic-datasource can not find primary datasource

项目启动报错信息 Caused by: com.baomidou.dynamic.datasource.exception.CannotFindDataSourceException: dynamic-datasource can not find primary datasourceat com.baomidou.dynamic.datasource.DynamicRoutingDataSource.determinePrimaryDataSource(DynamicRoutingDat…

国产信创领跑者:暴雨信息的创新与实践

随着数字化转型的加速推进&#xff0c;信创产业作为数字经济发展的重要支柱&#xff0c;正日益受到社会各界的广泛关注。在这个大背景下&#xff0c;暴雨信息积极响应国家号召&#xff0c;全面适配国产化&#xff0c;推动信创产业的技术创新和应用拓展&#xff0c;成为了行业的…

springboot基础案例(二)

文章目录 前言一.需求分析: 分析这个项目含有哪些功能模块二.库表设计(概要设计): 1.分析系统有哪些表 2.分析表与表关系 3.确定表中字段(显性字段 隐性字段(业务字段))2.1 创建一个库: ems-thymeleaf2.2 创建 2张表三.编码(环境搭建)1.创建一个springboot项目 项目名字: ems-t…

如何将SD卡众多文件打包成一个.img文件方便Windows的Windisk32工具一键烧写?

相信不少SOC FPGA用户在第一次设计SD卡image时都参考过Intel的经典教程 EmbeddedLinuxBeginnerSGuide &#xff0c;教程里面演示制作SD卡image时&#xff0c; 需要将SD卡手动分成3分区&#xff08;fat32、raw 和ext3&#xff09;&#xff0c;然后将preloader 、uboot、kernel、…

vue教程-介绍与使用

vue介绍 介绍 是一套用于构建用户界面的渐进式框架。与其它大型框架不同的是&#xff0c;Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层&#xff0c;不仅易于上手&#xff0c;还便于与第三方库或既有项目整合。 安装 最简单的例子就是&#xff0c;创建一个htm…