当前位置: 首页 > news >正文

网格图--Day03--网格图DFS--2658. 网格图中鱼的最大数目,1034. 边界着色,1020. 飞地的数量

网格图–Day03–网格图DFS–2658. 网格图中鱼的最大数目,1034. 边界着色,1020. 飞地的数量

今天要训练的题目类型是:【网格图DFS】,题单来自@灵艾山茶府。

适用于需要计算连通块个数、大小的题目。

部分题目做法不止一种,也可以用 BFS 或并查集解决。

DFS函数中的三步曲:判断,处理,继续DFS

  • 判断:是否越界,是否是需要DFS的格子
  • 处理:根据题意处理格子
  • 继续DFS:DFS四个方向,有时候可能需要收集返回值。

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

思路:

题意转换:0是水,val是陆地宝藏的数值,找到有最大数值宝藏的陆地。

是不是理解起来就简单多了?

遍历每一块陆地,对比它的价值。找到最大价值。

class Solution {// 题意转换:0是水,val是陆地宝藏的数值,找到有最大数值宝藏的陆地。private final int[][] DIRS = { { 1, 0 }, { 0, 1 }, { -1, 0 }, { 0, -1 } };private int dfs(int[][] grid, int i, int j) {if (i < 0 || j < 0 || i >= grid.length || j >= grid[0].length || grid[i][j] == 0) {return 0;}int val = grid[i][j];// 标记为已访问grid[i][j] = 0;// 用foreach写,看起来更简洁了for (int[] d : DIRS) {val += dfs(grid, i + d[0], j + d[1]);}return val;}public int findMaxFish(int[][] grid) {int n = grid.length;int m = grid[0].length;int res = 0;for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {if (grid[i][j] != 0) {int val = dfs(grid, i, j);res = Math.max(res, val);}}}return res;}
}

1034. 边界着色

思路:

题目非常啰嗦且复杂,感觉在做阅读题…………

题意:给指定陆地描边

  • DFS染色的时候,先染在temp矩阵上,dfs完之后再转移回去到grid,不然会影响遍历。复杂很多。
  • 题目说的边界要求:
    • 情况一:上下左右,只要有跟自己的color不同的,就算边界。染色!
    • 情况二:当前格子在边界上,就算边界。染色!
  • DFS下一个节点:要和本节点颜色相同,且没访问过的节点,才能进去。
  • 最后DFS完了,将temp上染色的格子,染回去grid
class Solution {// 题意:给指定陆地描边private final int[][] DIRS = { { 1, 0 }, { 0, 1 }, { -1, 0 }, { 0, -1 } };// 染色,先染在temp上,dfs完之后再转移回去到grid,不然会影响遍历。复杂很多。private void dfs(int[][] grid, int i, int j, int color, boolean[][] visited, int[][] temp) {// 标记已访问visited[i][j] = true;// 情况一:上下左右,只要有跟自己的color不同的,就算边界。染色!int cur = grid[i][j];if (i - 1 >= 0 && grid[i - 1][j] != cur|| i + 1 < grid.length && grid[i + 1][j] != cur|| j - 1 >= 0 && grid[i][j - 1] != cur|| j + 1 < grid[0].length && grid[i][j + 1] != cur) {temp[i][j] = color;}// 情况二:格子在边界上,就算边界。染色!if (i == 0 || j == 0 || i == grid.length - 1 || j == grid[0].length - 1) {temp[i][j] = color;}for (int k = 0; k < DIRS.length; k++) {int x = i + DIRS[k][0];int y = j + DIRS[k][1];// xy越界if (x < 0 || y < 0 || x >= grid.length || y >= grid[0].length) {continue;}// 下一个没访问过的节点,且这个节点要和当前节点是同色的if (!visited[x][y] && grid[x][y] == cur) {dfs(grid, x, y, color, visited, temp);}}}public int[][] colorBorder(int[][] grid, int row, int col, int color) {int n = grid.length;int m = grid[0].length;boolean[][] visited = new boolean[n][m];int[][] temp = new int[n][m];dfs(grid, row, col, color, visited, temp);// dfs完了之后,将temp上染色的格子,染回去gridfor (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {if (temp[i][j] != 0) {grid[i][j] = temp[i][j];}}}return grid;}
}

思路:

不用temp数组的版本。

关键在于:要先判断节点是否被visited过,再判断上下左右是否不同颜色。

这个顺序不能换。因为如果visited过了,颜色可能已经被改了,判断就会有误。

这个顺序是可以不用temp的原因。

public class Solution {// 题意:给指定陆地描边private final int[][] DIRS = { { 1, 0 }, { 0, 1 }, { -1, 0 }, { 0, -1 } };public int[][] colorBorder(int[][] grid, int row, int col, int color) {int m = grid.length;int n = grid[0].length;boolean[][] visited = new boolean[m][n];dfs(grid, row, col, grid[row][col], color, visited);return grid;}private int dfs(int[][] grid, int i, int j, int curColor, int paintColor,boolean[][] visited) {// 情况一:越界,说明上一个格子是边界if (i < 0 || j < 0 || i >= grid.length || j >= grid[0].length) {return 1;}// 已访问过的单元格if (visited[i][j]) {return 0;}// 这个顺序不能换,要先判断visited,再判断颜色相同。因为如果visited过了,颜色可能已经被改了,判断就会有误。// 情况二:遇到不同颜色的单元格,说明当前单元格是边界if (grid[i][j] != curColor) {return 1;}// 标记为已访问visited[i][j] = true;// 检查四个方向int isBorder = 0;for (int[] d : DIRS) {isBorder += dfs(grid, i + d[0], j + d[1], curColor, paintColor, visited);}// 如果任何一个方向返回1,说明当前单元格是边界,需要着色// 最后才着色if (isBorder > 0) {grid[i][j] = paintColor;}return 0;}
}

1020. 飞地的数量

思路:

题意:求内陆。

陆地中,必须至少有一个格子要碰到边界,否则这个陆地就是所求陆地(内陆)。

  • DFS搜索图中的每一个岛屿,累加返回每个岛屿的面积。
  • 判断岛屿是否接触边界,如果没有接触边界(内陆),就是所求陆地,累加它的面积到res中。
class Solution {// 题意:陆地中,必须至少有一个格子要碰到边界,否则这个陆地就是所求陆地(内陆)。private final int[][] DIRS = { { 0, 1 }, { 1, 0 }, { -1, 0 }, { 0, -1 } };private boolean connect = false;private int dfs(int[][] grid, int i, int j) {// 越界了,证明递归进来之前,是在边界上的。trueif (i < 0 || j < 0 || i >= grid.length || j >= grid[0].length) {connect = true;return 0;}// 0不一定是边界,这俩条件不能合在一起if (grid[i][j] == 0) {return 0;}// 标记已访问grid[i][j] = 0;// DFS累加,求这个岛的面积int area = 1;for (int k = 0; k < DIRS.length; k++) {int x = i + DIRS[k][0];int y = j + DIRS[k][1];area += dfs(grid, x, y);}return area;}public int numEnclaves(int[][] grid) {int n = grid.length;int m = grid[0].length;int res = 0;for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {// 在这里进去每次都是一个独立的岛屿,要把connect重置if (grid[i][j] == 1) {connect = false;int area = dfs(grid, i, j);// 如果还是没碰到边界,是所求的岛屿,累加到resif (!connect) {res += area;}}}}return res;}
}
http://www.xdnf.cn/news/1408591.html

相关文章:

  • Cartographer中的gflag与lua文件
  • 【开题答辩全过程】以 基于Java的城市公交查询系统设计与实现为例,包含答辩的问题和答案
  • 记录测试环境hertzbeat压测cpu高,oom问题排查。jvm,mat,visulavm
  • 浏览器和 node 操作文件的 api 以及区别
  • GEE 实战:Landsat 5 月度 NDVI 数据插值填补(以 8 月为例)_后附完整代码
  • Python:如何批量下载CLMS NDVI V3数据集?
  • PyQt5 K线图实现与性能优化详解
  • 神州数码之FTP/TFTP 升级 篇
  • 深入解析Linux系统中的/etc/hosts文件
  • 在Windows的wsl中如何以root登录Ubuntu
  • OpenStack 02:使用 DevStack 单节点一体化部署
  • Kafka面试精讲 Day 3:Producer生产者原理与配置
  • Java提供高效后端支撑,Vue呈现直观交互界面,共同打造的MES管理系统,含完整可运行源码,实现生产计划、执行、追溯一站式管理,提升制造执行效率
  • isp图像处理--bayer Binning
  • isp 图像处理--DPC坏点矫正
  • 张柏芝亮相林家谦演唱会 再次演绎《任何天气》
  • 秋招笔记-8.31
  • 【ACP】2025-最新-疑难题解析- 练习一汇总
  • 矩阵待办ios app Tech Support
  • 【机器学习】-torch相关知识01
  • IO_hw_8.29
  • 8.31【A】scons,带宽,语义semantic,读论文颜色规范,系统运行命令
  • 在Ubuntu系统上安装和配置JMeter和Ant进行性能测试
  • 【数学史冷知识】关于行列式的发展史
  • kkfile一键部署-ubuntu版
  • 云计算与服务器
  • 大模型参数量与计算量(FLOPs)估算方法
  • 【Flink】并行度的设置
  • 从 JDK 8 到 JDK 17
  • dify docker知识库topk最大值参数配置