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.
Example 1:
Input: grid = [[2,1,1],[1,1,0],[0,1,1]] Output: 4
Example 2:
Input: 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.
Example 3:
Input: grid = [[0,2]] Output: 0 Explanation: Since there are already no fresh oranges at minute 0, the answer is just 0.
Constraints:
m == grid.lengthn == grid[i].length1 <= m, n <= 10grid[i][j] is 0, 1, or 2.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:
We are simulating the process of oranges rotting over time. The brute force method involves repeatedly checking the entire grid to see which fresh oranges can become rotten in the next minute.
Here's how the algorithm would work step-by-step:
def oranges_rotting_brute_force(grid):
rows = len(grid)
columns = len(grid[0]) if rows > 0 else 0
minutes_passed = 0
fresh_oranges_count = 0
rotten_oranges_locations = []
# Count initial fresh oranges and find initially rotten ones
for row_index in range(rows):
for column_index in range(columns):
if grid[row_index][column_index] == 1:
fresh_oranges_count += 1
elif grid[row_index][column_index] == 2:
rotten_oranges_locations.append((row_index, column_index))
# Keep simulating minutes as long as there are fresh oranges and rotting can occur
while fresh_oranges_count > 0:
newly_rotten_this_minute = []
oranges_rotted_in_this_pass = False
# Check every cell for fresh oranges adjacent to rotten ones
for row_index in range(rows):
for column_index in range(columns):
if grid[row_index][column_index] == 1:
is_adjacent_to_rotten = False
# Check adjacent cells
for dr, dc in [(0, 1), (0, -1), (1, 0), (-1, 0)]:
neighbor_row, neighbor_column = row_index + dr, column_index + dc
if 0 <= neighbor_row < rows and 0 <= neighbor_column < columns and grid[neighbor_row][neighbor_column] == 2:
is_adjacent_to_rotten = True
break
if is_adjacent_to_rotten:
newly_rotten_this_minute.append((row_index, column_index))
oranges_rotted_in_this_pass = True
# If no oranges rotted in this pass, it means we can't rot any more
if not oranges_rotted_in_this_pass:
break
# Update the grid and counts for the next minute
for r, c in newly_rotten_this_minute:
grid[r][c] = 2
fresh_oranges_count -= 1
rotten_oranges_locations.append((r,c))
minutes_passed += 1
# If there are still fresh oranges left, it's impossible to rot them all
if fresh_oranges_count > 0:
return -1
else:
return minutes_passedThis problem is about finding the minimum time for all fresh oranges to rot. The key idea is to simulate the rotting process layer by layer, similar to how a ripple spreads outwards, starting from the initially rotten oranges.
Here's how the algorithm would work step-by-step:
from collections import deque
def orangesRotting(grid):
rows = len(grid)
columns = len(grid[0])
rotten_oranges_queue = deque()
fresh_oranges_count = 0
time_elapsed = 0
# Initialize queue with all rotten oranges and count fresh ones.
for rowIndex in range(rows):
for columnIndex in range(columns):
if grid[rowIndex][columnIndex] == 2:
rotten_oranges_queue.append((rowIndex, columnIndex, 0))
elif grid[rowIndex][columnIndex] == 1:
fresh_oranges_count += 1
# Directions for adjacent cells: up, down, left, right.
directions = [(-1, 0), (1, 0), (0, -1), (0, 1)]
# Process rotten oranges layer by layer (BFS).
while rotten_oranges_queue:
currentRow, currentColumn, currentTime = rotten_oranges_queue.popleft()
time_elapsed = max(time_elapsed, currentTime)
# Explore adjacent cells.
for dr, dc in directions:
neighborRow = currentRow + dr
neighborColumn = currentColumn + dc
# Check if the neighbor is within grid bounds and is a fresh orange.
if 0 <= neighborRow < rows and 0 <= neighborColumn < columns and grid[neighborRow][neighborColumn] == 1:
grid[neighborRow][neighborColumn] = 2 # Mark as rotten.
fresh_oranges_count -= 1
rotten_oranges_queue.append((neighborRow, neighborColumn, currentTime + 1))
# If there are still fresh oranges, they are unreachable.
if fresh_oranges_count > 0:
return -1
return time_elapsed| Case | How to Handle |
|---|---|
| Empty grid (m=0 or n=0) | The solution should return 0 minutes immediately if the grid is empty or has zero dimensions, as there are no oranges to rot. |
| Grid with no fresh oranges initially | If there are no fresh oranges (value 1) present at the start, the rotting time is 0 minutes, regardless of rotten oranges or empty cells. |
| Grid with only empty cells (all 0s) | If the grid contains only empty cells, no oranges can ever rot, and the function should return 0 minutes if no fresh oranges were present, or -1 if fresh oranges were somehow expected but impossible to rot. |
| Grid with only fresh oranges and no rotten oranges to start | If there are fresh oranges but no rotten oranges to initiate the rotting process, it's impossible for all fresh oranges to rot, so return -1. |
| A single fresh orange is isolated and cannot be reached by any rotten orange | If a fresh orange is surrounded by empty cells or other fresh oranges with no path to a rotten orange, it will never rot, leading to an impossible scenario and a return value of -1. |
| All oranges are already rotten (all 2s) | If all oranges are already rotten, no time is needed for rotting, and the function should return 0. |
| A grid where fresh oranges form disconnected components, some reachable by rotten oranges and some not | The algorithm must correctly identify all fresh oranges that become rotten and return -1 if any fresh orange remains unrotten. |
| Very large grid dimensions leading to memory or time limits | A BFS approach using a queue is generally efficient for large grids as it visits each cell at most a constant number of times, scaling well with grid size. |