Rotting Oranges

MediumBFS · Multi-Source Level Order🧩 Graph BFSLeetCode #994 ↗Updated

Problem

A grid holds 0 (empty), 1 (fresh orange) or 2 (rotten orange). Every minute, each rotten orange spoils the fresh oranges directly above, below, left and right of it. Return the number of minutes until no fresh orange is left, or -1 if some fresh orange can never be reached.
Input[[2,1,1],[1,1,0],[0,1,1]]Output4
Input[[2,1,1],[0,1,1],[1,0,1]]Output-1
Input[[0,2]]Output0

1 ≤ m, n ≤ 10  ·  grid[i][j] ∈ {0, 1, 2}

Try it yourself

Java
class Solution {
    public int orangesRotting(int[][] grid) {
        
    }
}
Your code is saved in this browser.Submit on LeetCode ↗
Key insight
All initially rotten oranges spread simultaneously, so put them all in the queue at once (multi-source BFS). Each BFS level is exactly one minute.
PatternGraph BFS

Instinct Minimum moves, fewest steps or shortest transformation where every step costs the same: spread outward level by level with a queue.

Memory hack Ripples in a pond: every ring is one step farther, so the first ring that touches the target is the answer.

Open the Graph BFS guide →

Approaches

Brute ForceMinute-by-Minute Grid Simulation

Time O((m·n)2)Space O(m·n)

Simulate literally: each round, scan the whole grid and collect every fresh orange touching a rotten one; rot them all after the scan (so the spread is one step per minute). Stop when a round changes nothing, then check for leftovers.

Java
public int orangesRotting(int[][] grid) {
    int m = grid.length, n = grid[0].length, minutes = 0;
    int[][] dirs = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
    while (true) {
        List<int[]> toRot = new ArrayList<>();
        for (int r = 0; r < m; r++) {
            for (int c = 0; c < n; c++) {
                if (grid[r][c] != 1) continue;
                for (int[] d : dirs) {
                    int nr = r + d[0], nc = c + d[1];
                    if (nr >= 0 && nr < m && nc >= 0 && nc < n && grid[nr][nc] == 2) {
                        toRot.add(new int[]{r, c});
                        break;
                    }
                }
            }
        }
        if (toRot.isEmpty()) break;
        for (int[] p : toRot) grid[p[0]][p[1]] = 2; // apply after the scan
        minutes++;
    }
    for (int[] row : grid)
        for (int v : row) if (v == 1) return -1;
    return minutes;
}

Obviously correct, but rescans the full grid up to m·n times.

At a glance

LevelApproachTimeSpace
Brute ForceMinute-by-Minute Grid SimulationO((m·n)2)O(m·n)
OptimalMulti-Source BFS (Level = Minute)O(m·n)O(m·n)
Common pitfalls
  • Rotting oranges during the scan in the simulation — one minute spreads many steps.
  • Running one BFS per rotten orange instead of seeding all of them at once.
  • Returning 0 vs -1: no fresh oranges at all ⇒ 0.
Interview tips
  • Say “multi-source BFS” early — it signals you see the simultaneous spread.
  • Explain why BFS (not DFS): levels give the minimum time to reach each cell.
  • Mention you mutate the grid as the visited set; offer a copy if mutation is disallowed.
Pattern
Multi-source BFS → several starting points spread at the same speed and you need the time/distance to cover everything.
My notes saved in this browser