【LeetCode 热题100】BFS/DFS 实战:岛屿数量 & 腐烂的橘子(力扣200 / 994 )(Go语言版)

🌊 BFS/DFS 实战:岛屿数量 & 腐烂的橘子(LeetCode 200 & 994)

两道图论基础题,涉及 BFS 与 DFS 的应用,主要用于掌握二维网格中遍历与标记访问的技巧:

  • 🏝️ 200. 岛屿数量(Number of Islands)
  • 🍊 994. 腐烂的橘子(Rotting Oranges)

🏝️ 一、200. 岛屿数量

📌 题目描述

给定一个由 '1'(陆地)和 '0'(水)组成的二维网格,计算岛屿的数量。

岛屿总是由相邻的陆地连接组成(水平或垂直),并且被水包围。


💡 解题思路

这道题的核心是:对每一个未被访问的陆地进行一次 DFS 或 BFS,将整块陆地标记为已访问,岛屿数量 +1

✅ 方法一:DFS 深度优先遍历
  • 从每个为 '1' 的位置出发,递归淹没它相邻的陆地;
  • 每次新的 DFS 开始,即发现了一个新的岛屿。
go 复制代码
func numIslands(grid [][]byte) int {
    m, n := len(grid), len(grid[0])
    var dfs func(int, int)
    dfs = func(i, j int) {
        if i < 0 || j < 0 || i >= m || j >= n || 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)
    }

    count := 0
    for i := 0; i < m; i++ {
        for j := 0; j < n; j++ {
            if grid[i][j] == '1' {
                dfs(i, j)
                count++
            }
        }
    }
    return count
}
✅ 方法二:BFS 广度优先遍历
  • 使用队列,每次将 '1' 入队后,通过四个方向将邻接陆地逐个加入队列。

🧠 小结

技术点 说明
核心思想 将一整块陆地用 DFS/BFS 访问并标记
遍历方式 DFS / BFS 均可
时间复杂度 O(m × n)
空间复杂度 DFS:O(m × n)(递归栈),BFS:队列空间

🍊 二、994. 腐烂的橘子

📌 题目描述

在一个二维网格中:

  • 0 代表空单元格,
  • 1 代表新鲜橘子,
  • 2 代表腐烂橘子。

每分钟,所有腐烂橘子会让上下左右相邻的新鲜橘子变腐烂

求腐烂完所有橘子的最短分钟数,如果无法全部腐烂,返回 -1


💡 解题思路

这是标准的多源 BFS 问题,初始队列中包含所有腐烂橘子的位置,然后每轮向周围传播。

✅ 步骤总结:
  1. 初始化队列,将所有腐烂橘子的坐标加入;
  2. 记录新鲜橘子的数量 fresh
  3. 每轮扩散一层(即一分钟),对新鲜橘子变腐烂,fresh--
  4. 最终看 fresh 是否为 0,若是返回分钟数,否则返回 -1。

📦 Go 实现
go 复制代码
type pair struct{ x, y int }

func orangesRotting(grid [][]int) int {
    m, n := len(grid), len(grid[0])
    queue := []pair{}
    fresh := 0

    for i := 0; i < m; i++ {
        for j := 0; j < n; j++ {
            if grid[i][j] == 2 {
                queue = append(queue, pair{i, j})
            } else if grid[i][j] == 1 {
                fresh++
            }
        }
    }

    dirs := []pair{{0, 1}, {1, 0}, {0, -1}, {-1, 0}}
    minutes := 0

    for len(queue) > 0 && fresh > 0 {
        size := len(queue)
        for i := 0; i < size; i++ {
            curr := queue[0]
            queue = queue[1:]
            for _, d := range dirs {
                x, y := curr.x + d.x, curr.y + d.y
                if x >= 0 && y >= 0 && x < m && y < n && grid[x][y] == 1 {
                    grid[x][y] = 2
                    fresh--
                    queue = append(queue, pair{x, y})
                }
            }
        }
        minutes++
    }

    if fresh > 0 {
        return -1
    }
    return minutes
}

⚠️ 注意事项

  • 初始化时要统计新鲜橘子的数量
  • 每一轮是批量扩散(多源 BFS)
  • 不能单独计数某个腐烂橘子的时间,要整体一起推进。

🔚 总结对比

特性 岛屿数量(200) 腐烂的橘子(994)
模型 连通块计数 最短传播路径,多源 BFS
算法 DFS / BFS BFS(层级扩散)
是否需要标记访问
特别关注 连通性与计数 初始状态和时间控制

相关推荐
花自向阳开10245 小时前
LeetCode hot100-11
数据结构·算法·leetcode
月亮被咬碎成星星5 小时前
LeetCode[404]左叶子之和
算法·leetcode
_Itachi__8 小时前
LeetCode 热题 100 208. 实现 Trie (前缀树)
算法·leetcode·职场和发展
闻闻不会编程8 小时前
74. 搜索二维矩阵 (力扣)
算法·leetcode·矩阵
海码0079 小时前
【Hot 100】70. 爬楼梯
数据结构·c++·算法·leetcode·动态规划·hot100
@蓝莓果粒茶12 小时前
LeetCode第244题_最短单词距离II
c++·笔记·学习·算法·leetcode·职场和发展·c#
无聊的小坏坏13 小时前
二分查找的边界艺术:LeetCode 34 题深度解析
算法·leetcode
緈福的街口13 小时前
【leetcode】20. 有效的括号
linux·算法·leetcode
@蓝莓果粒茶16 小时前
LeetCode第245题_最短单词距离III
c语言·c++·笔记·学习·算法·leetcode·c#
闻闻不会编程16 小时前
704. 二分查找 (力扣)
数据结构·算法·leetcode