58. Rotting Oranges
In grid, 0 is empty, 1 is a fresh orange and 2 is a rotten orange. Every minute, fresh oranges next to a rotten one (up/down/left/right) become rotten.
Return the minutes until no fresh orange is left, or -1 if that never happens.
Example 1
grid = [[2,1,1],[1,1,0],[0,1,1]]4Example 2
grid = [[2,1,1],[0,1,1],[1,0,1]]-1Hint 1
Start a BFS from ALL rotten oranges at the same time (multi-source BFS).
Hint 2
Each BFS layer is one minute.
Approach 1: Simulate minute by minute
Rescan the grid every minute.
Approach 2: Multi-source BFS ✅
Queue every rotten orange first, then expand layer by layer.
Reference solution for Multi-source BFS (time O(m · n), space O(m · n)). Each solution passes every test in all four languages.
class Solution:
def orangesRotting(self, grid: List[List[int]]) -> int:
m, n = len(grid), len(grid[0])
q = deque((r, c) for r in range(m) for c in range(n) if grid[r][c] == 2) # all sources at once
fresh = sum(row.count(1) for row in grid)
minutes = 0
while q and fresh:
for _ in range(len(q)): # one BFS layer = one minute
r, c = q.popleft()
for nr, nc in ((r + 1, c), (r - 1, c), (r, c + 1), (r, c - 1)):
if 0 <= nr < m and 0 <= nc < n and grid[nr][nc] == 1:
grid[nr][nc] = 2
fresh -= 1
q.append((nr, nc))
minutes += 1
return -1 if fresh else minutesclass Solution {
public int orangesRotting(int[][] grid) {
int m = grid.length, n = grid[0].length, fresh = 0, minutes = 0;
ArrayDeque<int[]> q = new ArrayDeque<>();
for (int r = 0; r < m; r++)
for (int c = 0; c < n; c++) {
if (grid[r][c] == 2) q.add(new int[]{r, c});
else if (grid[r][c] == 1) fresh++;
}
int[][] dirs = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
while (!q.isEmpty() && fresh > 0) {
for (int k = q.size(); k > 0; k--) { // one layer = one minute
int[] cur = q.poll();
for (int[] d : dirs) {
int nr = cur[0] + d[0], nc = cur[1] + d[1];
if (nr >= 0 && nc >= 0 && nr < m && nc < n && grid[nr][nc] == 1) {
grid[nr][nc] = 2; fresh--; q.add(new int[]{nr, nc});
}
}
}
minutes++;
}
return fresh > 0 ? -1 : minutes;
}
}class Solution {
public:
int orangesRotting(vector<vector<int>>& grid) {
int m = grid.size(), n = grid[0].size(), fresh = 0, minutes = 0;
queue<pair<int, int>> q;
for (int r = 0; r < m; r++)
for (int c = 0; c < n; c++) {
if (grid[r][c] == 2) q.push({r, c});
else if (grid[r][c] == 1) fresh++;
}
int dr[] = {1, -1, 0, 0}, dc[] = {0, 0, 1, -1};
while (!q.empty() && fresh > 0) {
for (int k = q.size(); k > 0; k--) { // one layer = one minute
auto [r, c] = q.front(); q.pop();
for (int d = 0; d < 4; d++) {
int nr = r + dr[d], nc = c + dc[d];
if (nr >= 0 && nc >= 0 && nr < m && nc < n && grid[nr][nc] == 1) {
grid[nr][nc] = 2; fresh--; q.push({nr, nc});
}
}
}
minutes++;
}
return fresh > 0 ? -1 : minutes;
}
};function orangesRotting(grid) {
const m = grid.length, n = grid[0].length;
let q = [], fresh = 0, minutes = 0;
for (let r = 0; r < m; r++) for (let c = 0; c < n; c++) {
if (grid[r][c] === 2) q.push([r, c]); else if (grid[r][c] === 1) fresh++;
}
while (q.length && fresh) {
const next = []; // one layer = one minute
for (const [r, c] of q)
for (const [nr, nc] of [[r + 1, c], [r - 1, c], [r, c + 1], [r, c - 1]])
if (nr >= 0 && nc >= 0 && nr < m && nc < n && grid[nr][nc] === 1) { grid[nr][nc] = 2; fresh--; next.push([nr, nc]); }
q = next;
minutes++;
}
return fresh ? -1 : minutes;
}Try solving it yourself first. Interviewers care more about how you explain the approach than about the finished code.
Watch the core idea of this problem step by step. Change the input and press Visualize.
Explained in the lesson Graphs: BFS & DFS.
Run your code to see results here.