LeetCode100 力扣热题100 岛屿数量

题目背景

这个问题是岛屿数量问题,给定一个由 '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)(递归栈的深度)。

这种方法能够高效地计算岛屿数量,同时避免重复计数岛屿。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值