Search
⌘K
Breadth-First Search

Rotting Oranges

medium

DESCRIPTION (inspired by Leetcode.com)

You are given an m x n grid representing a box of oranges. Each cell in the grid can have one of three values:

  1. "E" representing an empty cell
  2. "F" representing a fresh orange
  3. "R" representing a rotten orange

Every minute, any fresh orange that is adjacent (4-directionally: up, down, left, right) to a rotten orange becomes rotten.

Write a function that takes this grid as input and returns the minimum number of minutes that must elapse until no cell has a fresh orange. If it is impossible to rot every fresh orange, return -1.

Example 1:

Input:

grid = [
["R", "F"],
["F", "F"],
]

Output: 2

Explanation:

After Minute 1: The rotting orange at grid[0][0] rots the fresh oranges at grid[0][1] and grid[1][0]. After Minute 2: The rotting orange at grid[1][0] (or grid[0][1]) rots the fresh orange at grid[1][1].

So after 2 minutes, all the fresh oranges are rotten.

Example 2:

Input:

grid = [
["R", "E"],
["E", "F"],
]

Output: -1

Explanation:

The two adjacent oranges to the rotten orange at grid[0][0] are empty, so after 1 minute, there are no fresh oranges to rot. So it is impossible to rot every fresh orange.

Example 3:

Input:

grid = [
["R", "F", "F", "F"],
["F", "F", "F", "R"],
["E", "E", "F", "F"],
]

Output: 2

Explanation

We can model this problem as a graph where each cell is a node and the edges are the connections between adjacent cells.
The key to this problem is recognizing that we can simulate the rotting process using a breadth-first search (BFS) traversal of the graph (since any rotting orange will cause its neighbors to rot in the next minute).

Step 1: Initialize BFS Queue and Count Fresh Oranges

We can start by iterating over each cell in the grid and adding the position of all the rotten oranges to a queue. As we iterate, we can also count the number of fresh oranges in the grid - which will help us determine if there are any fresh oranges left after the BFS traversal.
RFF FFFR FFFFFQueue: [(0, 0), (1, 3)]Fresh Oranges: 9Minute: 0

Step 2: BFS Traversal

Next, we find all the oranges that will rot in the next minute. For each rotten orange in the BFS queue, we check if any of its neighbors are fresh oranges. If so, we turn the fresh orange into a rotten orange and add it to the queue to prepare for the next minute (shown in orange in the diagrams below). We also decrement the count of fresh oranges.
When we have finished processing all the rotten oranges in the queue, we increment the minute counter and repeat the process until there are no more fresh oranges left or the queue is empty.
RRF RRFR FFRRFQueue: [(0, 1), (1, 0), (0, 3), (1, 2), (2, 3)]Fresh Oranges: 5Minute: 1 RRR RRRR RFRRRQueue: [(0, 2), (1, 1), (2, 0), (2, 2)]Fresh Oranges: 1Minute: 2 RRR RRRR RRRRRQueue: [(2, 1)]Fresh Oranges: 0Minute: 3
The state of the orange box after each minute. The oranges that became rotten during this minute are colored in orange, while the "visited" oranges are dimmed.
If fresh_oranges is 0, then all oranges have become rotten, and we return the number of minutes it took to make all the oranges rotten. Otherwise, we return -1, as not all oranges can become rotten.

Solution

Solution
from collections import deque
class Solution:
def rotting_oranges(self, grid):
if not grid:
return -1
rows, cols = len(grid), len(grid[0])
queue = deque()
fresh_oranges = 0
# Step 1: Initialize BFS Queue and Count Fresh Oranges
for r in range(rows):
for c in range(cols):
if grid[r][c] == "R":
queue.append((r, c))
elif grid[r][c] == "F":
fresh_oranges += 1
# Step 2: Perform BFS to Simulate Rotting Process
directions = [(1, 0), (-1, 0), (0, 1), (0, -1)]
minutes = 0
while queue and fresh_oranges > 0:
minutes += 1
# process all the rotten oranges at the current minute
for _ in range(len(queue)):
x, y = queue.popleft()
for dx, dy in directions:
nx, ny = x + dx, y + dy
if 0 <= nx < rows and 0 <= ny < cols and grid[nx][ny] == "F":
grid[nx][ny] = "R"
fresh_oranges -= 1
queue.append((nx, ny))
return minutes if fresh_oranges == 0 else -1
Test Your Knowledge

Login to take the complexity quiz and track your progress

Complexity Analysis

Time Complexity: O(m * n) where m is the number of rows and n is the number of columns in the grid. The worst-case scenario is that all the cells in the grid are fresh oranges, and we have to visit all of them to rot them.

Space Complexity: O(m * n) where m is the number of rows and n is the number of columns in the grid. The space complexity is dominated by the queue used for the BFS traversal, which can contain at most m * n elements in the worst case.

Mark as read

Your account is free and you can post anonymously if you choose.

Unlock Premium Coding Content

Interactive algorithm visualizations
Reading Progress

On This Page