【LeetCode】200. 岛屿数量

leetcode

 

解题思路

岛屿数量问题要求在由 '0'(水)和 '1'(陆地)组成的二维网格中,统计被水包围的岛屿数量。岛屿定义为​​水平或垂直方向相邻​​的陆地连接形成的区域。核心解决思路是​​深度优先搜索(DFS)​​:

  1. ​​遍历扫描​​:遍历网格每个单元格
  2. ​​陆地触发​​:遇到陆地('1')时启动DFS
  3. ​​岛屿标记​​:DFS将当前岛屿所有陆地标记为水('0'),避免重复计数
  4. ​​计数递增​​:每次DFS启动表示发现新岛屿,计数器+1

该算法属于​​Flood Fill(泛洪算法)​​,通过DFS"淹没"已发现的岛屿

关键步骤

  1. ​​网格遍历​​:双重循环遍历每个单元格
  2. ​​陆地检测​​:当 grid[i][j] == '1' 时:
    • 岛屿计数器+1
    • 启动DFS淹没当前岛屿
  3. ​​DFS淹没过程​​:
    • 检查边界:若越界或已是水则返回
    • 标记当前:将陆地改为水('1'→'0')
    • 递归访问:上、下、左、右四个方向
  4. ​​方向处理​​:使用方向偏移量简化代码(非必需但更优雅)

代码实现

func numIslands(grid [][]byte) int {
    if len(grid) == 0 {
        return 0
    }

    rows, cols := len(grid), len(grid[0])
    count := 0

    // 定义DFS淹没函数
    var dfs func(int, int)
    dfs = func(i, j int) {
        // 边界检查: 越界或遇到水则返回
        if i < 0 || j < 0 || i >= rows || j >= cols || grid[i][j] == '0' {
            return
        }

        // 淹没当前陆地
        grid[i][j] = '0'

        // 递归淹没四个方向
        dfs(i+1, j) //
        dfs(i-1, j) //
        dfs(i, j+1) //
        dfs(i, j-1) //
    }

    // 主循环: 遍历网格
    for i := 0; i < rows; i++ {
        for j := 0; j < cols; j++ {
            if grid[i][j] == '1' {
                count++   // 发现新岛屿
                dfs(i, j) // 淹没整个岛屿
            }
        }
    }

    return count
}

示例测试

func main() {
    // 示例1:1个岛屿
    grid1 := [][]byte{
        {'1', '1', '1', '1', '0'},
        {'1', '1', '0', '1', '0'},
        {'1', '1', '0', '0', '0'},
        {'0', '0', '0', '0', '0'},
    }
    fmt.Println(numIslands(grid1)) // 输出: 1

    // 示例2:3个岛屿
    grid2 := [][]byte{
        {'1', '1', '0', '0', '0'},
        {'1', '1', '0', '0', '0'},
        {'0', '0', '1', '0', '0'},
        {'0', '0', '0', '1', '1'},
    }
    fmt.Println(numIslands(grid2)) // 输出: 3

    // 边界测试:空网格
    fmt.Println(numIslands([][]byte{})) // 输出: 0

    // 单岛屿测试
    grid3 := [][]byte{{'1'}}
    fmt.Println(numIslands(grid3)) // 输出: 1
}

复杂度分析

​​指标​​​​值​​​​说明​​
​​时间复杂度​​ O(m×n) 每个单元格最多访问1次(m=行数,n=列数)
​​空间复杂度​​ O(m×n) DFS递归栈深度最坏情况下达m×n(全陆地网格)

关键点总结

  1. ​​DFS淹没机制​​:

    • 通过递归将相连陆地标记为水
    • 确保每个岛屿只计数一次
  2. ​​原地修改优化​​:

    • 直接修改输入网格,避免额外空间
    • 将访问过的陆地改为'0'作为标记
  3. ​​方向处理技巧​​:

    • 显式写出四个方向(上、下、左、右)
    • 替代方案:使用方向数组dirs = [][2]int{{-1,0}, {1,0}, {0,-1}, {0,1}}
  4. ​​边界检查顺序​​:

    • ​​先检查越界​​再访问网格
    • 避免数组越界崩溃
posted @ 2025-06-17 16:05  云隙之间  阅读(32)  评论(0)    收藏  举报