题目背景
这个问题是岛屿数量问题,给定一个由 '1'(陆地)和 '0'(水域)组成的网格,计算并返回其中岛屿的数量。一个岛屿是由相邻的陆地组成,陆地可以是水平或垂直相邻。
思路
我们可以使用深度优先搜索(DFS)来遍历每个岛屿。DFS 会遍历每个 '1' 组成的连通区域,将其标记为 '0',表示已经访问过。每次遇到一个 '1' 时,都会启动一次 DFS 来将整片岛屿都标记掉,并增加岛屿计数。
关键步骤:
1. 遍历网格:遍历每个网格单元,如果它是 '1',表示发现一个新的岛屿。
2. 深度优先搜索(DFS):每发现一个新的岛屿,从这个 '1' 开始,使用 DFS 标记这个岛屿的所有陆地为 '0',避免重复计算。
3. 岛屿计数:每次启动 DFS 之后,岛屿计数增加。
代码注释
class Solution {public:// 主函数,计算岛屿的数量int numIslands(vector<vector<char>>& grid) {int ans = 0; // 用于计数岛屿数量// 遍历网格的每个位置for(int i = 0; i < grid.size(); i++) { // 遍历每一行for(int j = 0; j < grid[0].size(); j++) { // 遍历每一列if(grid[i][j] == '1') { // 找到一个岛屿ans++; // 增加岛屿计数dfs(grid, i, j); // 启动 DFS 来标记整个岛屿}}}return ans; // 返回岛屿的数量}// 深度优先搜索函数,用来标记岛屿中的每个陆地void dfs(vector<vector<char>>& grid, int i, int j) {// 如果位置越界或者当前点是水域('0'),则返回if(i < 0 || j < 0 || i >= grid.size() || j >= grid[0].size() || grid[i][j] == '0') {return;}// 将当前陆地标记为水域('0'),表示已访问grid[i][j] = '0';// 递归调用 DFS,访问四个方向的邻居(上下左右)dfs(grid, i + 1, j); // 向下dfs(grid, i - 1, j); // 向上dfs(grid, i, j + 1); // 向右dfs(grid, i, j - 1); // 向左}};
思路总结
1. 岛屿计数:我们遍历整个网格,遇到 '1' 就意味着发现了一个新的岛屿。然后启动 DFS,将这个岛屿标记掉。
2. DFS 标记岛屿:从当前 '1' 开始,DFS 会向上下左右四个方向扩展,找到所有连接的 '1',并将它们标记为 '0',表示已访问。
3. 递归边界条件:DFS 的递归条件判断是,越界或者遇到 '0'(水域)就返回,不再继续深入。
运行步骤
假设给定的 grid 是一个 4x5 的二维矩阵:
grid = [
['1', '1', '1', '0', '0'],
['1', '1', '0', '0', '0'],
['0', '0', '1', '0', '0'],
['0', '0', '0', '1', '1']
]
1. 初始化
• ans = 0,表示岛屿数量初始化为 0。
2. 遍历网格
1. 第一行: ['1', '1', '1', '0', '0']
• grid[0][0] = '1',启动 DFS,ans++,ans = 1,然后将岛屿位置 '1' 转换为 '0'。
• DFS 会标记 grid[0][0], grid[0][1], grid[0][2] 为 '0'。
2. 第二行: ['1', '1', '0', '0', '0']
• grid[1][0] = '1',但因为之前 DFS 已经把其标记为 '0',所以跳过。
• grid[1][1] = '1',也被标记为 '0'。
3. 第三行: ['0', '0', '1', '0', '0']
• grid[2][2] = '1',启动 DFS,ans++,ans = 2,然后将岛屿位置 '1' 转换为 '0'。
• DFS 会标记 grid[2][2] 为 '0'。
4. 第四行: ['0', '0', '0', '1', '1']
• grid[3][3] = '1',启动 DFS,ans++,ans = 3,然后将岛屿位置 '1' 转换为 '0'。
• DFS 会标记 grid[3][3], grid[3][4] 为 '0'。
3. 返回结果
• 最终 ans = 3,表示网格中有 3 个岛屿。
边界条件和优化
1. 空网格:如果 grid 是一个空矩阵,代码会自动跳过,因为 grid.size() 为 0,不会进入循环。
2. 大网格:该算法使用了深度优先搜索(DFS),时间复杂度为 O(m * n),其中 m 和 n 分别是矩阵的行数和列数。对于每个节点,DFS 会被访问一次,因此时间复杂度是线性的。
总结
• 岛屿数量的计算:通过 DFS 遍历每个 '1',每遇到一个未访问过的陆地(岛屿)就启动 DFS 来将其完全标记。
• 复杂度:时间复杂度为 O(m * n),空间复杂度为 O(m * n)(递归栈的深度)。
这种方法能够高效地计算岛屿数量,同时避免重复计数岛屿。