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

DFS岛屿问题:核心思想与实战模板

一、DFS 岛屿问题核心思想

岛屿问题本质是二维网格 DFS + 洪水填充

  1. 遍历网格每一个位置
  2. 遇到陆地 (1),以当前点为起点向上下左右四个方向递归遍历
  3. 遍历过的陆地原地标记为海洋 (0),避免重复访问
  4. 完整走完一片连通陆地,即为一个岛屿

二、通用前置模板(方向数组)

四个移动方向:上、下、左、右,刷题标准写法

// 方向数组:行偏移、列偏移 int dir[4][2] = {{-1,0}, {1,0}, {0,-1}, {0,1}};

三、基础 DFS 递归函数模板

// grid:二维网格,x,y:当前坐标,m/n:行列总数 void dfs(vector<vector<char>>& grid, int x, int y, int m, int n) { // 越界判定:坐标不在网格内,直接返回 if(x < 0 || x >= m || y < 0 || y >= n) return; // 当前不是陆地,返回 if(grid[x][y] != '1') return; // 标记已访问:陆地改为海洋 grid[x][y] = '0'; // 遍历四个方向递归搜索 for(int i = 0; i < 4; i++) { int nx = x + dir[i][0]; int ny = y + dir[i][1]; dfs(grid, nx, ny, m, n); } }

四、经典例题 1:岛屿数量(LeetCode 200)

题目描述

给定由'1'(陆地)和'0'(海洋)组成的二维网格,计算岛屿总数。陆地相邻为上下左右,斜向不算。

完整可运行代码

#include <iostream> #include <vector> using namespace std; int dir[4][2] = {{-1,0},{1,0},{0,-1},{0,1}}; void dfs(vector<vector<char>>& grid, int x, int y, int m, int n) { if(x < 0 || x >= m || y < 0 || y >= n || grid[x][y] != '1') return; grid[x][y] = '0'; for(int i = 0; i < 4; i++) { int nx = x + dir[i][0]; int ny = y + dir[i][1]; dfs(grid, nx, ny, m, n); } } int numIslands(vector<vector<char>>& grid) { if(grid.empty()) return 0; int m = grid.size(); int n = grid[0].size(); int count = 0; // 遍历整个网格 for(int i = 0; i < m; i++) { for(int j = 0; j < n; j++) { if(grid[i][j] == '1') { count++; dfs(grid, i, j, m, n); } } } return count; } int main() { vector<vector<char>> grid = { {'1','1','0','0','0'}, {'1','1','0','0','0'}, {'0','0','1','0','0'}, {'0','0','0','1','1'} }; cout << "岛屿数量:" << numIslands(grid) << endl; return 0; }

五、经典例题 2:最大岛屿面积

题目描述

求网格中面积最大的岛屿,面积为陆地单元格数量。

int dir[4][2] = {{-1,0},{1,0},{0,-1},{0,1}}; int dfsArea(vector<vector<int>>& grid, int x, int y, int m, int n) { if(x < 0 || x >= m || y < 0 || y >= n || grid[x][y] == 0) return 0; grid[x][y] = 0; int area = 1; // 当前单元格面积 for(int i = 0; i < 4; i++) { int nx = x + dir[i][0]; int ny = y + dir[i][1]; area += dfsArea(grid, nx, ny, m, n); } return area; } int maxAreaOfIsland(vector<vector<int>>& grid) { if(grid.empty()) return 0; int m = grid.size(); int n = grid[0].size(); int maxArea = 0; for(int i = 0; i < m; i++) { for(int j = 0; j < n; j++) { if(grid[i][j] == 1) { int cur = dfsArea(grid, i, j, m, n); maxArea = max(maxArea, cur); } } } return maxArea; }

六、岛屿类题目通用解题步骤

  1. 定义四方向数组,控制遍历方向
  2. 编写 DFS 函数:先判越界 + 判非陆地,再标记访问
  3. 四个方向递归扩散
  4. 双层循环遍历整张网格,遇到陆地就启动 DFS
  5. 根据题目要求:计数 / 求面积 / 求周长等

七、DFS 岛屿题拓展题型

  1. 岛屿周长
  2. 封闭岛屿
  3. 被围绕的区域
  4. 图像渲染(颜色填充)
  5. 网格中的路径搜索

八、新手易错点

  1. 忘记边界越界判断,数组下标越界崩溃
  2. 遍历后不修改原网格,造成重复遍历、死递归
  3. 方向数组写错,漏方向 / 多方向
  4. 行列 m、n 混淆,判断条件颠倒

九、DFS 优缺点回顾

  • 优点:代码简短、逻辑直观,洪水填充首选
  • 缺点:网格极大时,递归深度过深栈溢出,此时改用 BFS

十、今日总结

  1. 岛屿问题 = 二维网格 DFS + 洪水填充
  2. 四方向数组是标准配置,务必熟记
  3. 原地修改网格标记访问,无需额外 visited 数组
  4. 岛屿数量、最大面积是两大入门必背模板
http://www.cnnetsun.cn/news/2585014.html

相关文章:

  • Switch游戏文件编辑完全手册:专业级工具深度解析与实战指南
  • 【卫星】基于matlab卫星星座的红外跟踪可配置弹道导弹轨迹,从地球上任何起点和目的地【含Matlab源码 15670期】
  • Lovable数据分析平台落地全周期拆解(从零部署到高阶建模全流程)
  • 免费CRM系统有哪些?一文分清真假免费,中小企业零成本选型攻略
  • LNLF-BERT:基于双层级注意力机制的长文本处理模型解析与实践
  • 场感知矩阵分解:从传统协同过滤到上下文感知推荐的跃迁
  • 收藏!AI大模型内卷终结!摩根大通揭秘国内AI商业化颠覆性变革,小白也能抓住万亿新风口
  • 别乱改!RootPort的Completion Timeout值设大了,小心CPU的MCE错误来得更猛
  • H.264压缩域低码率鲁棒水印:原理、实现与工程实践
  • AI入门图像识别 目标检测与跟踪+区域识别+车道线流量计数
  • Wireshark 3.6.3 Windows安装深度指南:驱动、权限与NDIS兼容性实战
  • STM32实战:FatFS R0.14b文件系统移植与外部FLASH读写优化
  • android-sqlite3:从官方 SQLite 源码自动构建 Android 可用的 sqlite3
  • 2026 免费视频去水印工具对比、免费视频去水印工具推荐,免费用什么工具
  • Claude 4.7 Opus 智能应用落地实战指南
  • Image2 AI 创意挑战赛,灵感出圈赢大奖
  • 融合扩散模型与SMOTE:解决类别不平衡的混合增强框架DiSMHA
  • 打造全屋语音中枢:基于ESP8266的红外遥控器智能化改造实战
  • 普通人用不明白Gemini生论文插图,不如国产工具搞定AI矢量图
  • 基于语义相似度的NDN物联网服务发现优化策略
  • 仅剩72小时!Springer Nature刚更新的ChatGPT引用新规已生效——你的参考文献可能已不合规
  • 5G-Advanced NLOS识别:基于深度自编码核密度模型的信道异常检测
  • JMeter分布式压测5大配置陷阱与多机同步校验实战
  • 哔咔漫画下载器完整指南:3步打造个人离线漫画图书馆
  • 8 个搞定 RMAN 备份核查的实用 SQL 语句
  • OpenCV for Unity内存桥接与实时视觉管线实战
  • Unity il2cpp元数据解析异常根因与修复指南
  • OAuth 2.0与OpenID Connect本质区别:授权与认证的分层实践
  • STM32定时器编码器模式实战:不用外部中断,四倍频测速原来这么简单
  • 百度网盘直链解析:3分钟实现全速下载的完整指南