The tell: Simultaneous spread from several sources, measured in steps — multi-source BFS.
How you get there
1Seed the queue with every rotten cell at once, so all sources advance together.
2Each BFS level is one minute of elapsed time.
3If fresh oranges remain when the queue empties, they were unreachable.
Solution
Python
from collections import deque
def oranges_rotting(grid: list[list[int]]) -> int:
rows, cols = len(grid), len(grid[0])
queue = deque()
fresh = 0
for r in range(rows):
for c in range(cols):
if grid[r][c] == 2:
queue.append((r, c)) # every source seeded up front
elif grid[r][c] == 1:
fresh += 1
minutes = 0
while queue and fresh:
for _ in range(len(queue)):
r, c = queue.popleft()
for dr, dc in ((1, 0), (-1, 0), (0, 1), (0, -1)):
nr, nc = r + dr, c + dc
if 0 <= nr < rows and 0 <= nc < cols and grid[nr][nc] == 1:
grid[nr][nc] = 2
fresh -= 1
queue.append((nr, nc))
minutes += 1
return -1 if fresh else minutes
Time
O(rows · cols)
Space
O(rows · cols)
What goes wrong
Running BFS from each rotten cell separately gives the wrong time; they must spread simultaneously.