You are given an m x n
grid
where each cell can have one of three values:
0
representing an empty cell,1
representing a fresh orange, or2
representing a rotten orange.Every minute, any fresh orange that is 4-directionally adjacent to a rotten orange becomes rotten.
Return the minimum number of minutes that must elapse until no cell has a fresh orange. If this is impossible, return -1
.
For example:
Example 1:
grid = [[2,1,1],[1,1,0],[0,1,1]]
Output: 4
Example 2:
grid = [[2,1,1],[0,1,1],[1,0,1]]
Output: -1
Explanation: The orange in the bottom left corner (row 2, column 0) is never rotten, because rotting only happens 4-directionally.
Follow-up Question:
Can you solve this problem with a Breadth-First Search (BFS) approach for better efficiency?
When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
The brute force approach is like watching the oranges rot in real-time and meticulously tracking what happens. We repeatedly simulate the rotting process, checking every orange in every round, until no more oranges can rot. This continues until we either rot all the fresh oranges or reach a point where no more rotting can occur.
Here's how the algorithm would work step-by-step:
def rotting_oranges_brute_force(grid):
number_of_rows = len(grid)
number_of_columns = len(grid[0])
minutes_elapsed = 0
while True:
oranges_to_rot = []
# Iterate through the grid to find rotten oranges
for row in range(number_of_rows):
for column in range(number_of_columns):
if grid[row][column] == 2:
#Check adjacent cells for fresh oranges to rot.
if row > 0 and grid[row-1][column] == 1:
oranges_to_rot.append((row-1, column))
if row < number_of_rows - 1 and grid[row+1][column] == 1:
oranges_to_rot.append((row+1, column))
if column > 0 and grid[row][column-1] == 1:
oranges_to_rot.append((row, column-1))
if column < number_of_columns - 1 and grid[row][column+1] == 1:
oranges_to_rot.append((row, column+1))
#If no oranges were rotted this round, check to exit.
if not oranges_to_rot:
break
#Mark fresh oranges as rotten after checking neighbors.
for row, column in oranges_to_rot:
grid[row][column] = 2
minutes_elapsed += 1
#Check if any fresh oranges remain
fresh_oranges_exist = False
for row in range(number_of_rows):
for column in range(number_of_columns):
if grid[row][column] == 1:
fresh_oranges_exist = True
break
if fresh_oranges_exist:
break
if fresh_oranges_exist and not oranges_to_rot:
return -1
#After the loop, fresh oranges can still exist
for row in range(number_of_rows):
for column in range(number_of_columns):
if grid[row][column] == 1:
return -1
return minutes_elapsed
The best way to solve this problem is to simulate the rotting process step by step. We treat the grid like a map and track how the rot spreads from existing rotten oranges to nearby fresh ones. This approach avoids repeatedly checking the same oranges.
Here's how the algorithm would work step-by-step:
def rotting_oranges(grid):
rows = len(grid)
cols = len(grid[0])
rotten_oranges_queue = []
fresh_oranges_count = 0
for row in range(rows):
for col in range(cols):
if grid[row][col] == 2:
rotten_oranges_queue.append((row, col))
elif grid[row][col] == 1:
fresh_oranges_count += 1
minutes_elapsed = 0
directions = [(0, 1), (0, -1), (1, 0), (-1, 0)]
# Start the rotting process simulation.
while rotten_oranges_queue:
next_level_rotten_oranges = []
# Process all oranges rotting at the current minute
for row, col in rotten_oranges_queue:
for delta_row, delta_col in directions:
new_row = row + delta_row
new_col = col + delta_col
if 0 <= new_row < rows and 0 <= new_col < cols and grid[new_row][new_col] == 1:
# Mark fresh orange as rotten.
grid[new_row][new_col] = 2
fresh_oranges_count -= 1
next_level_rotten_oranges.append((new_row, new_col))
if next_level_rotten_oranges:
minutes_elapsed += 1
# The next level becomes current.
rotten_oranges_queue = next_level_rotten_oranges
# If any fresh oranges remain, it's impossible.
if fresh_oranges_count > 0:
return -1
return minutes_elapsed
Case | How to Handle |
---|---|
Null or empty grid | Return 0 immediately since no oranges exist. |
Grid with no oranges (all cells are 0) | Return 0 immediately since no oranges exist to rot. |
Grid with only fresh oranges (all cells are 1) | Return -1 since oranges will never rot. |
Grid with only rotten oranges (all cells are 2) | Return 0 since all oranges are already rotten. |
Grid with one rotten orange and the rest fresh oranges | The solution should correctly calculate the time for all fresh oranges to rot. |
Grid with dimensions 1x1 | The solution should correctly handle this minimal grid. |
Grid with a very large number of oranges and a large grid size | The BFS approach should handle large grids efficiently, but consider potential memory usage if extremely large. |
Disjoint fresh orange groups where some groups cannot be reached by rotten oranges | Return -1 if any fresh oranges remain after processing all possible rotting steps. |