class Solution:
empty = 0
fresh = 1
rotten = 2
minute = 0
directions = [[-1, 0], [1, 0], [0, -1], [0, 1]]
def orangesRotting(self, grid: List[List[int]]) -> int:
# every iteration is one minute spent
# start at rotten orange then perform bfs
# do not run bfs on already run orange
# outer loop
# iterate through each cell in the grid
# if empty or fresh orange, return
# if rotten run bfs
# need a global minute counter that needs to be incremented
# bfs():
# if empty cell return
# bi-directionally run bfs
# increment minute after all 4 directions
# 0 1 2
# 0 [#,1,1]
# 1 [1,1,0]
# 2 [0,1,1]
# row = 0
# col = 0
# cell = 2
# q = (1,0), (0,1)
# curRow = 0
# curCol = 0
ROWS, COLS = len(grid), len(grid[0])
q = deque()
fresh = 0
for row in range(ROWS):
for col in range(COLS):
if grid[row][col] == self.fresh:
fresh += 1
if grid[row][col] == self.rotten:
q.append([row,col])
# we have counted all fresh oranges in our system
# we have added all rotten oranges in our queue
while q and fresh > 0:
for _ in range(len(q)): # one layer from all sources
curRow, curCol = q.popleft()
for changeInRow, changeInCol in self.directions:
newRow = curRow + changeInRow
newCol = curCol + changeInCol
if min(newRow, newCol) < 0 or newRow == len(grid) or newCol == len(grid[0]):
continue # out of bounds
if grid[newRow][newCol] == self.empty or grid[newRow][newCol] == self.rotten:
continue
fresh -= 1
grid[newRow][newCol] = self.rotten
q.append([newRow, newCol])
self.minute += 1
return self.minute if fresh == 0 else -1