Rotting Oranges
The problem description can be found in LeetCode.
Approach
From the input images, it is clear that this is a BFS problem. In fact, at every minute, the rotten oranges could expand at the usual four directions as a single step. This looks like a breadth expansion.
As usual, this is not a clearly implicit Graph problem, but a matrix can be easily adapted to it.
As for 01 Matrix, we can first initialize our queue with the rotten oranges, and then we can expand them by single steps. In the end, if the amount of rotten oranges (from minute 1 on) is equal to the original number of the fresh oranges, then it means that there is not a fresh orange left, so we can return the elapsed time (number of minutes).
Solution
from collections import deque
from enum import Enum
from typing import Deque, Iterator, List, Tuple
class Orange(Enum):
NONE = 0
FRESH = 1
ROTTEN = 2
class Solution:
def orangesRotting(self, grid: List[List[int]]) -> int:
# not ideal, but just to avoid to have too many function parameters
self.grid = grid
self.rows, self.cols = len(grid), len(grid[0])
num_fresh_oranges = 0
queue: Deque[Tuple[int, int]] = deque()
for row in range(self.rows):
for col in range(self.cols):
if grid[row][col] == Orange.FRESH.value:
num_fresh_oranges += 1
elif grid[row][col] == Orange.ROTTEN.value:
queue.append((row, col))
num_rotten_oranges, minutes = self.bfs(queue)
return minutes if num_fresh_oranges == num_rotten_oranges else -1
def bfs(self, queue: Deque[Tuple[int, int]]) -> Tuple[int, int]:
minutes = 0
num_rotten_oranges = 0
while queue:
for _ in range(len(queue)):
row, col = queue.popleft()
for nbr_row, nbr_col in self.get_neighbors(row, col):
self.grid[nbr_row][nbr_col] = Orange.ROTTEN.value
queue.append((nbr_row, nbr_col))
num_rotten_oranges += 1
if queue:
minutes += 1
return num_rotten_oranges, minutes
def get_neighbors(self, row: int, col: int) -> Iterator[Tuple[int, int]]:
deltas = [
(-1, 0), # up
(+1, 0), # down
(0, -1), # left
(0, +1), # right
]
for dt_row, dt_col in deltas:
nbr_row = row + dt_row
nbr_col = col + dt_col
if (
0 <= nbr_row < self.rows
and 0 <= nbr_col < self.cols
and self.grid[nbr_row][nbr_col] == Orange.FRESH.value
):
yield nbr_row, nbr_col
Complexity
- Time:
- Space:
Where and are the number of rows and columns of the input grid
, respectively.