在给定的 m x n 网格 grid 中,每个单元格可以有以下三个值之一:

值 0 代表空单元格; 值 1 代表新鲜橘子; 值 2 代表腐烂的橘子。 每分钟,腐烂的橘子 周围 4 个方向上相邻 的新鲜橘子都会腐烂。

返回直到单元格中没有新鲜橘子为止所必须经过的最小分钟数。如果不可能,返回 -1 。 image


此题是一个多源 BFS 问题。关键在于把几个循环嵌套的逻辑想清楚,同时能想到维护一个 fresh 变量作为新鲜橘子的个数,从而作为最终是否能够全部腐烂的判断依据。

C++54 linesExpandCollapse
int orangesRotting(vector<vector<int>>& grid) {
    
    int m = grid.size(), n = grid[0].size();
    
    int fresh = 0;
    int minutes = 0;
    
    queue<pair <int, int>> q;
    
    for (int i = 0; i < m; i++) {
        for (int j = 0; j < n; j++) {
            if (grid[i][j] == 1) fresh++;
            if (grid[i][j] == 2) q.push({i, j});
        }
    }
    
    if (fresh == 0) return 0;
    
    // 枚举 4 个方向
    int directions[4][2] = {
      {1, 0},
      {0, 1},
      {-1, 0},
      {0, -1}  
    };
    
    // 每轮循环代表一次 BFS,即 1 分钟
    while (!q.empty() && fresh > 0) {
        minutes++;
        int size = q.size();
        
        // 每轮循环对应一个当前队列中腐烂的橘子
        while (size--) {
            // 从队列中取出腐烂橘子的坐标
            auto [x, y] = q.front();
            q.pop();
            // 遍历 4 个方向的相邻位置
            for (auto& [dx, dy] : directions) {
                int newX = x + dx;
                int newY = y + dy;
                
                if (newX < 0 || newY < 0 || newX >= m || newY >= n || grid[newX][newY] != 1) {
                    continue;
                }
                
                grid[newX][newY] = 2;
                fresh--;
                q.push({newX, newY});
            }
        }
    }
    
    return fresh == 0 ? minutes : -1;
}