news 2026/7/7 21:10:58

代码随想录 463.岛屿的周长

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
代码随想录 463.岛屿的周长

思路:

1.网格问题:网格问题是这样的一类搜索问题:由m×n个小方格组成一个网格,每个小方格与其上下左右的四个方格被认为是相邻的,要在这样的网格上进行某种搜索。这种题目用DFS实现会非常简单。

2.如何构造方格类DFS的代码?

(1)首先,每个方格与其上下左右的四个方格相邻,则DFS每次要分出四个岔。

// 基本的 DFS 框架:每次搜索四个相邻方格 void dfs(int[][] grid, int r, int c) { dfs(grid, r - 1, c); // 上边相邻 dfs(grid, r + 1, c); // 下边相邻 dfs(grid, r, c - 1); // 左边相邻 dfs(grid, r, c + 1); // 右边相邻 }

(2)但是,对于网格边缘的方格,上下左右并不都有邻居。

思路一:在递归调用之前判断方格的位置,例如位于左边缘则不访问其左邻居。但这样一个一个判断写起来会比较麻烦。(×)

思路二:采用“先污染后治理”的思路,先做递归调用,再在每个DFS函数的开头判断其是否合法,不合法的直接返回。同样,还需要判断该方格是否有岛屿(值是否为1),否则也需要返回。(√)

// 处理方格位于网格边缘的情况 void dfs(int[][] grid, int r, int c) { // 若坐标不合法,直接返回 if (!(0 <= r && r < grid.length && 0 <= c && c < grid[0].length)) { return; } // 若该方格不是岛屿,直接返回 if (grid[r][c] != 1) { return; } dfs(grid, r - 1, c); dfs(grid, r + 1, c); dfs(grid, r, c - 1); dfs(grid, r, c + 1); }

(3)但这样还有一个问题,那就是DFS可能会不停地兜圈子,永远停不下来,如下图所示。

(4)那么我们需要标记遍历过的方格,保证方格不进行重复遍历。标记遍历过的方格并不需要使用额外空间,只需要改变方格中存储的值就可以。在这道题中,值为0表示非岛屿(不可遍历),值为1表示岛屿(可遍历),可以用2表示已经遍历过的岛屿。

(5)这样,就得到了网格DFS遍历的框架代码。

// 标记已遍历过的岛屿,不做重复遍历 void dfs(int[][] grid, int r, int c) { if (!(0 <= r && r < grid.length && 0 <= c && c < grid[0].length)) { return; } // 已遍历过(值为2)的岛屿在这里会直接返回,不会重复遍历 if (grid[r][c] != 1) { return; } grid[r][c] = 2; // 将方格标记为"已遍历" dfs(grid, r - 1, c); dfs(grid, r + 1, c); dfs(grid, r, c - 1); dfs(grid, r, c + 1); }

(6)如何在DFS遍历时求岛屿的周长:求岛屿周长的方法很多,如果用DFS遍历来求的话,有一种很简单的思路,那就是岛屿的周长就是岛屿方格和非岛屿方格相邻的边的数量。这里的非岛屿方格既包括水域,也包括网格的边界,如下图所示。

将这个相邻关系对应到DFS遍历中,就是:每当在DFS遍历中,从一个岛屿走向一个非岛屿方格,就将周长 + 1。代码如下所示。

int dfs(int[][] grid, int r, int c) { // 从一个岛屿方格走向网格边界,周长加 1 if (!(0 <= r && r < grid.length && 0 <= c && c < grid[0].length)) { return 1; } // 从一个岛屿方格走向水域方格,周长加 1 if (grid[r][c] == 0) { return 1; } if (grid[r][c] != 1) { return 0; } grid[r][c] = 2; return dfs(grid, r - 1, c) + dfs(grid, r + 1, c) + dfs(grid, r, c - 1) + dfs(grid, r, c + 1); }

附代码:

class Solution { public int islandPerimeter(int[][] grid) { for(int r = 0;r < grid.length;r++){ for(int c = 0;c < grid[0].length;c++){ if(grid[r][c] == 1){ //题目限制只有一个岛屿,计算一个即可 return dfs(grid,r,c); } } } return 0; } int dfs(int[][] grid,int r,int c){ //先污染后治理,只需要在开头判断是否合法,若不合法则直接返回 //从一个岛屿方格走向网格边界,周长加1 if(!(r >= 0 && r < grid.length && c >= 0 && c < grid[0].length)){ return 1; } //从一个岛屿方格走向水域方格,周长加1 if(grid[r][c] == 0){ return 1; } //已经遍历过,直接返回,避免重复遍历 if(grid[r][c] == 2){ return 0; } //将本方格标记为已经遍历过 grid[r][c] = 2; //探索相邻格子,并将四个方向的周长计算结果相加 return dfs(grid,r - 1,c) + dfs(grid,r + 1,c) + dfs(grid,r,c - 1) + dfs(grid,r,c + 1); } }
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/6 21:08:30

CSS小白必学:5分钟掌握文本溢出省略技巧

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 创建一个面向初学者的CSS教程示例&#xff0c;逐步讲解如何实现文本溢出显示省略号。要求&#xff1a;1. 从最基础的white-space/text-overflow属性讲起 2. 包含可视化示意图 3. 提…

作者头像 李华
网站建设 2026/7/7 16:07:53

15分钟构建可演示的AI容器化POC

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 开发一个端到端的AI演示系统&#xff1a;1) 使用预训练模型容器实现实时图像分类&#xff1b;2) 轻量级Web界面接收用户上传图片&#xff1b;3) 可视化推理结果和性能指标。要求&am…

作者头像 李华
网站建设 2026/7/7 16:20:35

告别低效:UTools如何节省开发者50%的时间

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 开发一个UTools插件&#xff0c;用于统计和分析用户的操作效率。插件应记录常用操作的时间消耗&#xff0c;提供优化建议&#xff0c;并展示使用UTools前后的效率对比图表。支持导出…

作者头像 李华
网站建设 2026/7/7 15:50:29

零基础图解教程:.deb安装就像手机装APP一样简单

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 开发一个面向Linux新手的.deb安装教学应用&#xff0c;功能包括&#xff1a;1. 交互式安装向导 2. 实时命令解释 3. 常见错误动画演示 4. 安全安装检查 5. 学习进度跟踪。要求使用大…

作者头像 李华
网站建设 2026/7/7 8:51:38

零基础玩转Phyfusion:你的第一个物理模拟项目

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 设计一个面向新手的Phyfusion入门教程项目。要求&#xff1a;1. 分三步实现弹跳球基础模拟&#xff08;创建场景→添加物理属性→运行&#xff09;&#xff1b;2. 每个步骤提供可视…

作者头像 李华
网站建设 2026/7/7 18:52:16

1小时开发:用Python打造专属批量改名工具

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 开发一个基于Python的快速批量改名工具原型。要求提供图形界面&#xff0c;支持&#xff1a;1) 选择文件或文件夹 2) 设置命名规则&#xff08;前缀、后缀、序号、日期等&#xff0…

作者头像 李华