-
Notifications
You must be signed in to change notification settings - Fork 17
/
Copy pathrotting-oranges.py
149 lines (119 loc) · 4.8 KB
/
rotting-oranges.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
from typing import List, Iterator, Tuple
from collections import deque
class Solution:
def orangesRotting(self, grid: List[List[int]]) -> int:
distances = [[float("+inf")] * len(grid[r]) for r in range(len(grid))]
rows, cols = len(grid), len(grid[0]) if grid else 0
def neighbors(row: int, col: int) -> Iterator[Tuple[int, int]]:
# Return all neighbors up, down, left, right if exist
for neigh_row, neigh_col in (
(row, col - 1),
(row - 1, col),
(row, col + 1),
(row + 1, col),
):
if (
neigh_row >= 0
and neigh_row < rows
and neigh_col >= 0
and neigh_col < cols
and grid[neigh_row][neigh_col] == 1
):
yield neigh_row, neigh_col
def dfs(row, col, distance) -> None:
if distance > distances[row][col]:
return
distances[row][col] = distance
for neigh_row, neigh_col in neighbors(row, col):
dfs(neigh_row, neigh_col, distance + 1)
def get_last_rotten() -> int:
result = 0
for row in range(rows):
for col in range(cols):
if grid[row][col] == 1:
if distances[row][col] == float("+inf"):
return -1
else:
result = max(result, int(distances[row][col]))
return result
for row in range(rows):
for col in range(cols):
if grid[row][col] == 2:
dfs(row, col, 0)
return get_last_rotten()
def orangesRottingBFS(self, grid: List[List[int]]) -> int:
distances = [[float("+inf")] * len(grid[r]) for r in range(len(grid))]
rows, cols = len(grid), len(grid[0]) if grid else 0
def neighbors(row, col):
# Return all neighbors up, down, left, right if exist
for neigh_row, neigh_col in (
(row, col - 1),
(row - 1, col),
(row, col + 1),
(row + 1, col),
):
if (
neigh_row >= 0
and neigh_row < rows
and neigh_col >= 0
and neigh_col < cols
and grid[neigh_row][neigh_col] == 1
):
yield neigh_row, neigh_col
queue = deque()
for row in range(rows):
for col in range(cols):
if grid[row][col] == 2:
queue.append((row, col, 0))
distances[row][col] = 0
while queue:
row, col, distance = queue.popleft()
if distance > distances[row][col]:
continue
distances[row][col] = distance
for neigh_row, neigh_col in neighbors(row, col):
queue.append((neigh_row, neigh_col, distance + 1))
result = 0
for row in range(rows):
for col in range(cols):
if grid[row][col] == 1:
if distances[row][col] == float("+inf"):
return -1
result = max(result, distances[row][col])
return result
def orangesRottingBFS2(self, grid: List[List[int]]) -> int:
rows, cols = len(grid), len(grid[0]) if grid else 0
queue = deque()
visited = set()
fresh = set()
for row in range(rows):
for col in range(cols):
if grid[row][col] == 2:
queue.append((row, col, 0))
visited.add((row, col))
fresh.add((row, col))
if grid[row][col] == 1:
fresh.add((row, col))
def neighbours(
row: int, col: int, rows: int, cols: int
) -> Iterator[Tuple[int, int]]:
for neigh_row, neigh_col in (
(row + 1, col),
(row - 1, col),
(row, col - 1),
(row, col + 1),
):
if 0 <= neigh_row < rows and 0 <= neigh_col < cols:
if (neigh_row, neigh_col) not in visited and grid[neigh_row][
neigh_col
] == 1:
yield (neigh_row, neigh_col)
total = 0
while queue:
row, col, minutes = queue.popleft()
fresh.remove((row, col))
total = max(total, minutes)
for neigh_row, neigh_col in neighbours(row, col, rows, cols):
queue.append((neigh_row, neigh_col, minutes + 1))
visited.add((neigh_row, neigh_col))
return -1 if fresh else total