994. Rotting Oranges
At a Glance
- Topic: graphs
- Pattern: BFS (multi-source, layered)
- Difficulty: Medium
- Companies: Amazon, Microsoft, Google, Meta, Apple
- Frequency: High
- LeetCode: 994
Problem (one-liner)
Grid 0 empty, 1 fresh orange, 2 rotten. Each minute, rotten infects 4-neighbors. Return minutes until no fresh remain, or -1 if impossible.
Recognition Cues
- Simultaneous propagation — minute cadence = BFS levels
- Multiple sources — enqueue all
2initially
Diagram
At-a-glance flow (replace with problem-specific Mermaid as you refine this note). camelCase node IDs; no spaces in IDs.
Loading diagram…
Approaches
- DFS timestamp — messy with correctness — avoid.
- Optimal — multi-source BFS —
O(nm)time,O(nm)queue.
Optimal Solution
Go
func orangesRotting(grid [][]int) int {
rows := len(grid)
cols := len(grid[0])
queue := make([][2]int, 0)
fresh := 0
for row := 0; row < rows; row++ {
for col := 0; col < cols; col++ {
if grid[row][col] == 2 {
queue = append(queue, [2]int{row, col})
} else if grid[row][col] == 1 {
fresh++
}
}
}
if fresh == 0 {
return 0
}
minutesElapsed := 0
directions := [][2]int{{1, 0}, {-1, 0}, {0, 1}, {0, -1}}
head := 0
for len(queue)-head > 0 && fresh > 0 {
waveCount := len(queue) - head
for step := 0; step < waveCount; step++ {
cell := queue[head]
head++
for _, delta := range directions {
nextRow := cell[0] + delta[0]
nextCol := cell[1] + delta[1]
if nextRow < 0 || nextCol < 0 || nextRow >= rows || nextCol >= cols {
continue
}
if grid[nextRow][nextCol] != 1 {
continue
}
grid[nextRow][nextCol] = 2
fresh--
queue = append(queue, [2]int{nextRow, nextCol})
}
}
minutesElapsed++
}
if fresh > 0 {
return -1
}
return minutesElapsed
}JavaScript
function orangesRotting(grid) {
const rows = grid.length;
const cols = grid[0].length;
const queue = [];
let fresh = 0;
for (let row = 0; row < rows; row += 1) {
for (let col = 0; col < cols; col += 1) {
if (grid[row][col] === 2) {
queue.push([row, col]);
} else if (grid[row][col] === 1) {
fresh += 1;
}
}
}
if (fresh === 0) {
return 0;
}
const directions = [
[1, 0],
[-1, 0],
[0, 1],
[0, -1],
];
let minutesElapsed = 0;
let head = 0;
while (queue.length - head > 0 && fresh > 0) {
const waveCount = queue.length - head;
for (let step = 0; step < waveCount; step += 1) {
const cell = queue[head];
head += 1;
for (const [deltaRow, deltaCol] of directions) {
const nextRow = cell[0] + deltaRow;
const nextCol = cell[1] + deltaCol;
if (nextRow < 0 || nextCol < 0 || nextRow >= rows || nextCol >= cols) {
continue;
}
if (grid[nextRow][nextCol] !== 1) {
continue;
}
grid[nextRow][nextCol] = 2;
fresh -= 1;
queue.push([nextRow, nextCol]);
}
}
minutesElapsed += 1;
}
return fresh === 0 ? minutesElapsed : -1;
}Walkthrough
Minute 0 rottens neighbors of initial layer; each round drains levelSize queue segment; stop when fresh==0.
Invariant: BFS layer index equals elapsed minutes for newly infected cells.
Edge Cases
- Already all rotten / no fresh —
0 - Unreachable fresh cell —
-1
Pitfalls
- Counting a minute when nothing changed in last layer — guard with
freshchecks
Similar Problems
- 286. Walls and Gates — multi-source shortest distance on grid
- 200. Number of Islands — grid propagation thinking
Variants
- Hex grid — change neighbor offsets
Mind-Map Tags
#bfs #multi-source #grid #level-order #shortest-time
Last updated on
Spotted something unclear or wrong on this page?