网格图的搜索

来自灵神网格图题单。

1. 网格图

1.1. LC 200 岛屿数量

这题我一开始想繁了,想维护并查集,然后看等价类个数。其实完全没有必要。因为连通分量深搜到头就可以直接给答案计数+1。利用vis数组维护访问过的点,然后碰到新连通分量重新深搜即可。因为有vis数组,所以每个节点至多访问一次,即O(nm)的复杂度。

import java.util.Arrays;class Solution {boolean[] vis;int m,n;int[][] direction = new int[][]{{-1,0},{0,1},{1,0},{0,-1}};public int numIslands(char[][] grid) {m = grid.length;n = grid[0].length;vis = new boolean[m*n];int ans = 0;for (int i = 0; i < m; i++) {for (int j = 0; j < n; j++) {if(grid[i][j]=='1'&&!vis[i*n+j]){dfs(grid,i,j);ans++;}}}return ans;}private void dfs(char[][] grid,int x,int y){if(vis[x*n+y]){return;}vis[x*n+y] = true;int nx,ny;for (int[] dir : direction) {nx = x+dir[0];ny = y+dir[1];if(indexValid(nx,ny)&&grid[nx][ny]=='1'){dfs(grid,nx,ny);}}}private boolean indexValid(int x,int y){return x>=0 && x<m && y>=0 && y<n;}
}

1.2. LC 695 岛屿的最大面积

这题和LC 200其实一样的。前者统计连通分量个数,这个统计最大连通分量元素个数。还是维护vis防止走重复,遇到新连通分支就统计这个连通分支元素数量,维护最大值就行。

class Solution {boolean[] vis;int m,n;int[][] directions = new int[][]{{-1,0},{0,1},{1,0},{0,-1}};public int maxAreaOfIsland(int[][] grid) {m = grid.length;n = grid[0].length;vis = new boolean[n*m];int max = 0;for (int i = 0; i < m; i++) {for (int j = 0; j < n; j++) {if(!vis[i*n+j] && grid[i][j]==1){max = Math.max(max,dfs(grid,i,j));}}}return max;}private int dfs(int[][] g,int x,int y){if(vis[x*n+y]){return 0;}vis[x*n+y] = true;int nx,ny;int cnt = 0;for (int[] direction : directions) {nx = x+direction[0];ny = y+direction[1];if(indexValid(nx,ny) && g[nx][ny]==1){cnt += dfs(g,nx,ny);}}return cnt+1;}private boolean indexValid(int x,int y){return x>=0 && x<m && y>=0 && y<n;}
}

1.3. LC 面试题16.19. 水域大小

和LC695差不多。维护每个连通分量大小,排个序返回就行。

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;class Solution {boolean[] vis;int m,n;int[][] dirs = new int[][]{{-1,0},{0,1},{1,0},{0,-1},{-1,-1},{-1,1},{1,-1},{1,1}};public int[] pondSizes(int[][] land) {m = land.length;n = land[0].length;vis = new boolean[m*n];List<Integer> tmp = new ArrayList<>();for (int i = 0; i < m; i++) {for (int j = 0; j < n; j++) {if(!vis[i*n+j]&&land[i][j]==0){tmp.add(dfs(land,i,j));}}}int[] ans = new int[tmp.size()];for (int i = 0; i < tmp.size(); i++) {ans[i] = tmp.get(i);}Arrays.sort(ans);return ans;}private int dfs(int[][] l,int x,int y){if(vis[x*n+y]){return 0;}vis[x*n+y]=true;int cnt = 0;int nx,ny;for (int[] dir : dirs) {nx = x+dir[0];ny = y+dir[1];if(indexValid(nx,ny)&&l[nx][ny]==0){cnt += dfs(l,nx,ny);}}return cnt+1;}private boolean indexValid(int x,int y){return x>=0 && x<m && y>=0 && y<n;}
}

1.4. LC 463 岛屿的周长

和200/695/16.19差不多,就是查一个连通分量。记得重复边不仅没有增量反而-1。另外由于题目明确说了就一个连通分量,因此查到一个后可以直接结束了。

class Solution {boolean[] vis;int m,n;int[][] dirs = new int[][]{{-1,0},{0,1},{1,0},{0,-1}};public int islandPerimeter(int[][] grid) {m = grid.length;n = grid[0].length;vis = new boolean[m*n];int ans = 0;for (int i = 0; i < m; i++) {for (int j = 0; j < n; j++) {if(!vis[i*n+j]&&grid[i][j]==1){ans = dfs(grid,i,j);break;}}}return ans;}private int dfs(int[][] g,int x,int y){if(vis[x*n+y]){return 0;}vis[x*n+y]=true;int cnt = 4;int nx,ny;for (int[] dir : dirs) {nx = x+dir[0];ny = y+dir[1];if(indexValid(nx,ny)&&g[nx][ny]==1){cnt+=dfs(g,nx,ny)-1;}}return cnt;}private boolean indexValid(int x,int y){return x>=0 && x<m && y>=0 && y<n;}
}

1.5. LC 2658 网格图中鱼的最大数目

这题一开始读错题了,以为是最大化连通分量中的最大值。但实际上是最大化连通分量元素和。还是跟以前一样套路,分开深搜维护最大值即可。

class Solution {boolean[] vis;int m,n;int[][] dirs = new int[][]{{-1,0},{0,1},{1,0},{0,-1}};public int findMaxFish(int[][] grid) {m = grid.length;n = grid[0].length;vis = new boolean[m*n];int max = 0;for (int i = 0; i < m; i++) {for (int j = 0; j < n; j++) {if(!vis[i*n+j]&&grid[i][j]>0){max = Math.max(max,dfs(grid,i,j));}}}return max;}private int dfs(int[][] g,int x,int y){if(vis[x*n+y]){return 0;}vis[x*n+y]=true;int nx,ny;int cnt = g[x][y];for (int[] dir : dirs) {nx = x+dir[0];ny = y+dir[1];if(indexValid(nx,ny)&&g[nx][ny]>0){cnt += dfs(g,nx,ny);}}return cnt;}private boolean indexValid(int x,int y){return x>=0 && x<m && y>=0 && y<n;}
}

1.7. LC 1020 飞地的数量

这道题虽然A了但是思路比较差。我是直接深搜,然后打一个标记位置,深搜到边界给标记位置置true,然后深搜返回的是连通块的大小。如果标记位为false说明连通块没有到边界,这样就可以累加。

但是更好的思路是,直接从边界深搜,把能抵达的1全部标记出来,剩下没标记的都是要求的。

import java.util.Arrays;class Solution {boolean[][] vis;int[][] directions = new int[][]{{-1,0},{0,1},{1,0},{0,-1}};int m,n;boolean flag;public int numEnclaves(int[][] grid) {m = grid.length;n = grid[0].length;vis = new boolean[m][n];int sum = 0;for (int i = 0; i < m; i++) {for (int j = 0; j < n; j++) {if(grid[i][j]==1&&!vis[i][j]){flag = false;int tmp = dfs(grid, i, j);if(!flag){sum+=tmp;}}}}return sum;}private int dfs(int[][] grid,int x,int y){if(vis[x][y]||grid[x][y]==0){return 0;}vis[x][y] = true;if(x==0||x==m-1||y==0||y==n-1){flag = true;}int nx,ny,sum;sum = 0;for (int[] direction : directions) {nx = x+direction[0];ny = y+direction[1];if(isValid(nx,ny)){sum += dfs(grid,nx,ny);}}return sum+1;}private boolean isValid(int x,int y){return x>=0 && x<m && y>=0 &&y<n;}
}

这个是我的。

class Solution {public int numEnclaves(int[][] grid) {int m = grid.length;int n = grid[0].length;for(int i = 0; i < m; i ++){if(grid[i][0] == 1) dfs(grid, i, 0, m, n);if(grid[i][n - 1] == 1) dfs(grid, i, n - 1, m , n);}for(int i = 0; i < n; i ++){if(grid[0][i] == 1) dfs(grid, 0, i, m, n);if(grid[m - 1][i] == 1) dfs(grid, m - 1, i, m ,n);}int res = 0;for(int i = 0; i < m; i ++){for(int j = 0; j < n; j ++){if(grid[i][j] == 1){res ++;}}}return res;}public void dfs(int[][] grid, int i, int j, int m, int n){if(i < 0 || j < 0 || i >= m || j >= n) return;if(grid[i][j] == 0) return;grid[i][j] = 0;dfs(grid, i + 1, j, m, n);dfs(grid, i - 1, j, m ,n);dfs(grid, i, j + 1, m, n);dfs(grid, i, j - 1, m, n);}
}

更好的思路。

1.8. LC 1254 统计封闭岛屿的数目

可以这么想,如果一个0的连通块存在元素在边界上,那么就不是封闭岛屿,反过来就是。这样深搜的时候检查是否到达过边界。如果没有到达过的话增1就可以了。

import java.util.Arrays;class Solution {int m,n;boolean[] vis;int[][] directions = new int[][]{{-1,0},{0,1},{1,0},{0,-1}};public int closedIsland(int[][] grid) {m = grid.length;n = grid[0].length;vis = new boolean[m*n];Arrays.fill(vis,false);int ans = 0;for (int i = 0; i < m; i++) {for (int j = 0; j < n; j++) {if(!vis[i*n+j]&&grid[i][j]!=1){if(!dfs(grid,i,j)){ans++;}}}}return ans;}private boolean isOnEdge(int x,int y){return x==0||y==0||x==m-1||y==n-1;}private boolean isValid(int x,int y){return x>=0 && x<m && y>=0 && y<n;}private boolean dfs(int[][] grid,int x,int y){if(grid[x][y]==1||vis[x*n+y]){return false;}vis[x*n+y] = true;int nx,ny;boolean flag = isOnEdge(x,y);for (int[] direction : directions) {nx = x+direction[0];ny = y+direction[1];if(isValid(nx,ny)){flag|=dfs(grid,nx,ny);}}return flag;}
}

1.9. LC 130 被围绕的区域

这题别和上题一样判断是否连通块有边界元素,因为判完再染之前深搜的可能漏染了。

可以这样,先从边界深搜,把边界上的O所在的连通块全访问掉。这样剩下的就是内部的了(被围绕的O),然后深搜内部染色就行。

class Solution {int m,n;boolean[][] vis;int[][] directions = new int[][]{{-1,0},{0,1},{1,0},{0,-1}};public void solve(char[][] board) {m = board.length;n = board[0].length;vis = new boolean[m][n];for (int i = 0; i < n; i++) {if(board[0][i]=='O'&&!vis[0][i]){dfs(board,0,i,true);}}for (int i = 0; i < n; i++) {if(board[m-1][i]=='O'&&!vis[m-1][i]){dfs(board,m-1,i,true);}}for (int i = 0; i < m; i++) {if(board[i][0]=='O'&&!vis[i][0]){dfs(board,i,0,true);}}for (int i = 0; i < m; i++) {if(board[i][n-1]=='O'&&!vis[i][n-1]){dfs(board,i,n-1,true);}}for (int i = 0; i < m; i++) {for (int j = 0; j < n; j++) {if(board[i][j]=='O'&&!vis[i][j]){dfs(board,i,j,false);}}}}private void dfs(char[][] g,int x,int y,boolean OnEdge){if(g[x][y]=='X'||vis[x][y]){return;}vis[x][y] = true;int nx,ny;for (int[] direction : directions) {nx = x+direction[0];ny = y+direction[1];if(isValid(nx,ny)){dfs(g,nx,ny,OnEdge);}}if(!OnEdge){g[x][y] ='X';}}private boolean isValid(int x,int y){return x>=0 && x<m && y>=0 && y<n;}
}

1.10. LC 1391 检查网格中是否存在有效路径

这题很恶心。首先要选择不同形状街道的行走方向,比如第一个街道既可以从左往右,又可以从右到左;第二得保证下一个格子的街道形状能够对接的上这个各自的街道形状。比如1可以拼接5但不能拼接6。这两个条件我打表了两个巨繁的数组。其中directions[i]是一个二维数组,表示值为i+1的单元格的行走方向,每个行走方向都是一个二维向量。accept[i]也是一个二维数组,表示值为i+1的单元格可以接受的街道形状的对应id-1。

class Solution {int m,n;int[][][] directions = new int[][][]{{{0,-1},{0,1}},{{-1,0},{1,0}},{{0,-1},{1,0}},{{0,1},{1,0}},{{0,-1},{-1,0}},{{0,1},{-1,0}}};int[][][] accept = new int[][][]{{{0,3,5},{0,2,4}},{{1,2,3},{1,4,5}},{{0,3,5},{1,4,5}},{{0,2,4},{1,4,5}},{{0,3,5},{1,2,3}},{{0,2,4},{1,2,3}}};boolean[][] vis;public boolean hasValidPath(int[][] grid) {m = grid.length;n = grid[0].length;vis = new boolean[m][n];return dfs(grid,0,0);}private boolean dfs(int[][] grid,int x,int y){if(x==m-1 && y==n-1){return true;}vis[x][y] = true;int nx,ny;int way = grid[x][y]-1;boolean flag = false;for (int i = 0; i < directions[way].length; i++) {nx = x+directions[way][i][0];ny = y+directions[way][i][1];if(isValid(nx,ny)&&!vis[nx][ny]){if(contains(accept[way][i],grid[nx][ny]-1)){flag|=dfs(grid,nx,ny);}}}return flag;}private boolean isValid(int x,int y){return x>=0 && x<m && y>=0 && y<n;}private boolean contains(int[] arr,int target){for (int i : arr) {if(i==target){return true;}}return false;}
}

其实还好,O(mn)的。就是写起来要有一堆规则,很恶心。

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

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

相关文章

Pinia使用

官方地址&#xff1a;Pinia | The intuitive store for Vue.js (vuejs.org)https://pinia.vuejs.org/ 1.安装 npm install pinia npm install pinia-plugin-persistedstate Pinia是一个基于Vue 3的状态管理库&#xff0c;它使得管理Vue的全局状态变得更加容易和直观。 而…

自定义el-dialog的样式

实现效果&#xff1a; 样式代码如下&#xff1a;&#xff08;可以写在common.scss文件夹中&#xff09; .el-dialog__header {padding: 16px 20px;border-bottom: 1px solid #DCDFE6;display: flex;align-items: center;.el-dialog__title {font-size: 16px;position: relativ…

utniy urp shinyssrr插件使用

文章目录 前言步骤1首先在URP的配置文件里添加SSR后处理2 修改RenderingPath为延迟渲染3 启用深度纹理4 为物体添加脚本 插件下载 前言 用来实现屏幕空间反射效果 unity 版本为2021.3.8LTS&#xff0c;低版本的untiy URP的参数设置位置z可能会不同 步骤 1首先在URP的配置文件…

记录阿里云换源失败的惨痛教训

声明 首先我不是一个云服务器小白&#xff0c;但是之前一直在使用腾讯云和火山引擎的云服务器。从未见过阿里云这样如此**的运营商。 问题 服务器到手&#xff0c;第一步在我进行sudo apt update的时候&#xff0c;也就是更新软件包的时候&#xff0c;我发现&#xff0c;一直…

1028. 从先序遍历还原二叉树(三种方法:栈+递归+集合)

文章目录 1028. 从先序遍历还原二叉树&#xff08;三种方法&#xff1a;栈递归集合&#xff09;一、栈 while迭代1.思路2.代码 二、递归法1.思路2.代码 三、集合存储1.思路2.代码 1028. 从先序遍历还原二叉树&#xff08;三种方法&#xff1a;栈递归集合&#xff09; 一、栈 wh…

hive报错:FAILED: NullPointerException null

发现问题 起因是我虚拟机的hive不管执行什么命令都报空指针异常的错误 我也在网上找了很多相关问题的资料&#xff0c;发现都不是我这个问题的解决方法&#xff0c;后来在hive官网上与hive 3.1.3版本相匹配的hadoop版本是3.x的版本&#xff0c;而我的hadoop版本还是2.7.2的版本…

HTTPS的加密过程

文章目录 前言一、为什么需要加密&#xff1f;二、只用对称加密可以吗&#xff1f;三、只使用非对称加密四、双方都使用非对称加密五、使用非对称加密对称加密六、引入证书1.如何放防止数字证书被篡改&#xff1f;2.中间人有可能篡改该证书吗&#xff1f;3.中间人有可能掉包该证…

开窗函数rank() over,dense_rank() over,row_number() over的区别

1.rank() over 查询出指定的条件进行排名&#xff0c;条件相同排名相同的话&#xff0c;排名之间是不连续的 例如排名如 1 2 3 3 5 6 7 等&#xff0c;相同的排名会自动跳过 2.dense_rank() over 查询出指定的条件后进行排名&#xff0c;条件相同&#xff0c;排名相同的话&…

【YOLO系列】YOLOv9论文超详细解读(翻译 +学习笔记)

前言 时隔一年&#xff0c;YOLOv8还没捂热&#xff0c;YOLO系列最新版本——YOLOv9 终于闪亮登场&#xff01; YOLOv9的一作和v7一样。v4也有他。 他于2017年获得台湾省National Central University计算机科学与信息工程博士学位&#xff0c;现在就职于该省Academia Sinica的…

【大数据】Flink SQL 语法篇(六):Temporal Join

《Flink SQL 语法篇》系列&#xff0c;共包含以下 10 篇文章&#xff1a; Flink SQL 语法篇&#xff08;一&#xff09;&#xff1a;CREATEFlink SQL 语法篇&#xff08;二&#xff09;&#xff1a;WITH、SELECT & WHERE、SELECT DISTINCTFlink SQL 语法篇&#xff08;三&…

机器视觉——硬件选型

1、相机选型 在选择机器视觉相机时&#xff0c;通常需要考虑以下几个方面&#xff1a; 1、分辨率&#xff1a;相机的分辨率决定了其拍摄图像的清晰度和细节程度。根据具体的应用需求&#xff0c;可以选择适当的分辨率范围。 2、帧率&#xff1a;帧率表示相机每秒钟能够拍摄的…

2023年营养保健品线上电商市场行业分析(2024年营养保健行业未来趋势分析)

近年来&#xff0c;受人口老龄化、养生年轻化等因素驱动&#xff0c;保健品行业增长强劲&#xff0c;加之越来越多的年轻人也加入养生大军&#xff0c;成为保健品市场上的一股新力量&#xff0c;进一步带动市场扩容。 鲸参谋数据显示&#xff0c;2023年度&#xff0c;京东平台…

[pdf]《软件方法》2024版部分公开-共196页

DDD领域驱动设计批评文集 做强化自测题获得“软件方法建模师”称号 《软件方法》各章合集 潘加宇《软件方法》2024版部分公开pdf文件&#xff0c;共196页&#xff0c;已上传CSDN资源。 也可到以下地址下载&#xff1a; http://www.umlchina.com/url/softmeth2024.html 如果…

Ubuntu20.04 ssh终端登录后未自动执行.bashrc

sudo vim ~/.profile输入以下内容 if [ -n "$BASH_VERSION" ]; then if [ -f "$HOME/.bashrc" ]; then . "$HOME/.bashrc" fi fi 执行 source ~/.profile重新测试 其他答案 如果你的~/.bashrc文件在Ubuntu中没有自动生效&#xff0c;…

3. 文档概述(Documentation Overview)

3. 文档概述&#xff08;Documentation Overview&#xff09; 本章节简要介绍一下Spring Boot参考文档。它包含本文档其它部分的链接。 本文档的最新版本可在 docs.spring.io/spring-boot/docs/current/reference/ 上获取。 3.1 第一步&#xff08;First Steps&#xff09; …

解析电源模块测试条件与测试步骤 快速完成测试

高温高湿储存测试是电源模块环境适应性测试内容之一&#xff0c;在实际使用过程中由于应用场景不同电源所处的环境也是多样的&#xff0c;因此需要测试电源对各种环境的适应能力&#xff0c;提高电源的性能和可靠性。 电源高温高湿存储测试的目的是为了测量环境对电源结构、元件…

C语言第三十三弹---动态内存管理(上)

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】 动态内存管理 1、为什么要有动态内存分配 2、malloc和free 2.1、malloc 2.2、free 3、calloc和realloc 3.1、calloc 3.2、realloc 4、常见的动态内存的错…

气象数据收集

1、国家气象科学数据中心 预报数据:需要定制,收费10万+ 观测数据:国家气象信息中心-中国气象数据网 (cma.cn)https://data.cma.cn/data/cdcdetail/dataCode/A.0012.0001.html 地面基本气象观测数据 滞后2天 滞后一天 路面数据同化系统,实时 国家气象信息中心-中国气象数…

11.以太网交换机工作原理

目录 一、以太网协议二、以太网交换机原理三、交换机常见问题思考四、同网段数据通信全过程五、跨网段数据通信全过程六、关键知识七、调试命令 前言&#xff1a;在网络中传输数据时需要遵循一些标准&#xff0c;以太网协议定义了数据帧在以太网上的传输标准&#xff0c;了解以…

android移动应用开发基础答案,安卓工程师面试题

一线企业的app都是多线程和多进程的&#xff0c;而Android进程间通信机制就是Binder&#xff0c;原生的线程间通信则是Handler&#xff0c;Binder和Handler是了解安卓运行机制必须要掌握的一个知识点&#xff0c;更是一线企业面试必问的知识点&#xff01; 以下几道就是大厂关于…