news 2026/9/12 10:28:59

岛屿数量问题:DFS/BFS与并查集算法解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
岛屿数量问题:DFS/BFS与并查集算法解析

1. 项目概述

"岛屿数量"是一个经典的算法问题,通常出现在编程面试和算法竞赛中。这个问题要求我们计算一个二维网格中"岛屿"的数量,其中'1'代表陆地,'0'代表水域。岛屿被定义为水平或垂直相邻的陆地组成的区域(对角线相邻不算)。

这个问题看似简单,但实际上考察了程序员对图论中深度优先搜索(DFS)和广度优先搜索(BFS)算法的理解,以及对矩阵遍历和边界条件处理的掌握程度。

2. 核心算法解析

2.1 问题建模

我们可以将给定的二维网格看作一个图,其中每个'1'的单元格是一个节点,相邻的'1'之间存在边。这样,岛屿数量问题就转化为计算图中连通分量的数量。

2.2 深度优先搜索(DFS)解法

DFS是最直观的解决方法。基本思路是:

  1. 遍历网格中的每个单元格
  2. 当遇到'1'时,开始DFS,将所有相连的'1'标记为已访问
  3. 岛屿数量加1
  4. 继续遍历直到所有单元格都被处理
def numIslands(grid): if not grid: return 0 count = 0 rows, cols = len(grid), len(grid[0]) for i in range(rows): for j in range(cols): if grid[i][j] == '1': dfs(grid, i, j) count += 1 return count def dfs(grid, i, j): if i < 0 or j < 0 or i >= len(grid) or j >= len(grid[0]) or grid[i][j] != '1': return grid[i][j] = '0' # 标记为已访问 dfs(grid, i+1, j) dfs(grid, i-1, j) dfs(grid, i, j+1) dfs(grid, i, j-1)

2.3 广度优先搜索(BFS)解法

BFS使用队列来实现,同样有效:

  1. 遍历网格中的每个单元格
  2. 当遇到'1'时,开始BFS,将所有相连的'1'标记为已访问
  3. 岛屿数量加1
  4. 继续遍历直到所有单元格都被处理
from collections import deque def numIslands(grid): if not grid: return 0 count = 0 rows, cols = len(grid), len(grid[0]) for i in range(rows): for j in range(cols): if grid[i][j] == '1': bfs(grid, i, j) count += 1 return count def bfs(grid, i, j): queue = deque() queue.append((i, j)) grid[i][j] = '0' while queue: x, y = queue.popleft() for dx, dy in [(1,0), (-1,0), (0,1), (0,-1)]: nx, ny = x + dx, y + dy if 0 <= nx < len(grid) and 0 <= ny < len(grid[0]) and grid[nx][ny] == '1': grid[nx][ny] = '0' queue.append((nx, ny))

3. 算法优化与变种

3.1 并查集(Union-Find)解法

并查集是解决连通性问题的经典数据结构,特别适合处理这类问题:

class UnionFind: def __init__(self, grid): rows, cols = len(grid), len(grid[0]) self.count = 0 self.parent = [i for i in range(rows * cols)] self.rank = [0] * (rows * cols) for i in range(rows): for j in range(cols): if grid[i][j] == '1': self.count += 1 def find(self, i): if self.parent[i] != i: self.parent[i] = self.find(self.parent[i]) return self.parent[i] def union(self, x, y): rootx = self.find(x) rooty = self.find(y) if rootx != rooty: if self.rank[rootx] > self.rank[rooty]: self.parent[rooty] = rootx elif self.rank[rootx] < self.rank[rooty]: self.parent[rootx] = rooty else: self.parent[rooty] = rootx self.rank[rootx] += 1 self.count -= 1 def numIslands(grid): if not grid: return 0 rows, cols = len(grid), len(grid[0]) uf = UnionFind(grid) for i in range(rows): for j in range(cols): if grid[i][j] == '1': grid[i][j] = '0' for dx, dy in [(1,0), (0,1)]: ni, nj = i + dx, j + dy if ni < rows and nj < cols and grid[ni][nj] == '1': uf.union(i * cols + j, ni * cols + nj) return uf.count

3.2 问题变种

  1. 统计岛屿周长:计算所有岛屿的周长总和
  2. 最大岛屿面积:找出所有岛屿中面积最大的
  3. 封闭岛屿数量:统计完全被水域包围的岛屿数量
  4. 不同形状岛屿:识别并统计不同形状的岛屿

4. 性能分析与优化

4.1 时间复杂度分析

  • DFS/BFS解法:O(M×N),其中M和N分别是网格的行数和列数
  • 并查集解法:接近O(M×N),但实际复杂度取决于具体实现

4.2 空间复杂度分析

  • DFS解法:最坏情况下O(M×N),递归栈的深度可能达到网格大小
  • BFS解法:O(min(M,N)),队列的大小最多为网格的较短边
  • 并查集解法:O(M×N),用于存储父节点和秩

4.3 优化技巧

  1. 原地修改:直接修改输入网格来标记已访问的单元格,节省空间
  2. 方向数组:使用方向数组简化相邻单元格的遍历
  3. 边界检查:在访问前检查边界条件,避免不必要的递归或入队
  4. 并行处理:对于大规模网格,可以考虑并行处理不同区域

5. 实际应用场景

岛屿数量问题不仅仅是算法练习,它在实际中有多种应用:

  1. 图像处理:识别和统计图像中的连通区域
  2. 地理信息系统:计算地图上的陆地面积或岛屿数量
  3. 游戏开发:在网格类游戏中检测封闭区域
  4. 社交网络分析:识别社交网络中的连通组件
  5. 电路设计:检测电路板上的连通区域

6. 常见问题与调试技巧

6.1 常见错误

  1. 忘记标记已访问的单元格:导致无限循环或重复计数
  2. 边界条件处理不当:数组越界访问
  3. 对角线相邻处理:题目通常要求水平或垂直相邻
  4. 输入为空的情况:没有处理空输入导致错误

6.2 调试技巧

  1. 打印中间状态:在DFS/BFS过程中打印当前处理的单元格
  2. 可视化网格:将网格状态可视化,便于理解算法执行过程
  3. 小规模测试:先用小网格测试,确保基本逻辑正确
  4. 边界测试:专门测试网格边缘和角落的情况

7. 扩展学习

对于想进一步深入学习的开发者,建议:

  1. 尝试解决LeetCode上相关的岛屿问题系列
  2. 学习更高级的图算法,如Tarjan算法
  3. 研究并行算法在网格问题中的应用
  4. 探索如何将这类算法应用到实际项目中

岛屿数量问题虽然基础,但它包含了算法设计和实现的许多重要概念。通过深入理解和实践这个问题,可以提升解决更复杂问题的能力。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/12 10:26:35

校园简讯App开发:微信小程序+Django实战解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/12 10:25:05

高职生在数据可视化领域的优势与职业发展

1. 高职生在数据可视化领域的独特优势数据可视化作为信息时代的重要技能&#xff0c;正在各行各业快速普及。高职院校培养的技术技能型人才在这一领域具有独特的竞争优势。与普通高校学生相比&#xff0c;高职生更注重实践操作和技能培养&#xff0c;这种教育模式恰好契合了数据…

作者头像 李华
网站建设 2026/9/12 10:22:48

Java+SSM实现大学生企业推荐系统:从算法模型到部署优化

简介&#xff1a;这是一份基于Java与SSM框架&#xff08;SpringSpringMVCMyBatis&#xff09;的大学生企业推荐系统完整源码&#xff0c;采用B/S结构与MySQL数据库&#xff0c;适合计算机相关专业学生作为课程设计、毕业设计或Java Web框架练手项目。系统包含管理员、学生、企业…

作者头像 李华
网站建设 2026/9/12 10:20:23

YOLO野生动物检测系统:从模型选型到SpringBoot工程落地

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华