Skip to content

Commit 7084ad9

Browse files
author
Joseph Luce
authored
Update shortest_distance_from_all_buildings.md
1 parent e914921 commit 7084ad9

File tree

1 file changed

+80
-1
lines changed

1 file changed

+80
-1
lines changed

real_interview_questions/Google/shortest_distance_from_all_buildings.md

Lines changed: 80 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ class Solution(object):
3434
:rtype: int
3535
"""
3636
n_buildings = sum(x.count(1) for x in grid)
37-
bfs_queue = collections.deque()
3837
result = -1
3938
4039
for row_index in range(0, len(grid)):
@@ -93,3 +92,83 @@ class Solution(object):
9392
return True
9493
return False
9594
```
95+
96+
# SOLUTION
97+
Instead of doing a BFS for all lands, we will utalize the fact that the question wants the sum of the distance as the answer. With this, we can instead BFS from each building instead. This will reduce the amount of BFS we have to perform. During each iteration of the BFS, we will use another array to store the distances of each land and how many buildings this land has been touched by a building. After all BFSes, we will look at the distance array and check for the min distance that have touched all buildings.
98+
```
99+
class Solution(object):
100+
def shortestDistance(self, grid):
101+
"""
102+
:type grid: List[List[int]]
103+
:rtype: int
104+
"""
105+
dp = [[[0,0] for _ in range(len(grid[0]))] for _ in range(len(grid))]
106+
n_buildings = 0
107+
108+
for row_index in range(0, len(grid)):
109+
for col_index in range(0, len(grid[0])):
110+
element = grid[row_index][col_index]
111+
if element == 1: # start with a building
112+
n_buildings += 1
113+
start_indexes = (row_index, col_index)
114+
local_result = self.bfs_all_lands(start_indexes, grid, dp)
115+
return self.find_shortest_distance(dp, n_buildings)
116+
117+
def find_shortest_distance(self, dp, n_buildings):
118+
result = sys.maxint
119+
reached_all_buildings = False
120+
for row_index in range(0, len(dp)):
121+
for col_index in range(0, len(dp[0])):
122+
dp_element = dp[row_index][col_index]
123+
if dp_element[1] == n_buildings:
124+
reached_all_buildings = True
125+
result = min(result, dp_element[0])
126+
if reached_all_buildings == False:
127+
return -1
128+
return result
129+
130+
def bfs_all_lands(self, start_indexes, grid, dp):
131+
# add all neighboring lands
132+
bfs_queue = collections.deque()
133+
visited_set = set()
134+
neighbors = self.get_land_neighbors(start_indexes, grid)
135+
for neighbor in neighbors:
136+
bfs_queue.appendleft(neighbor)
137+
visited_set.add(neighbor)
138+
distance = 0
139+
140+
while len(bfs_queue) != 0:
141+
n_pops = len(bfs_queue)
142+
distance += 1
143+
while n_pops > 0:
144+
curr_indexes = bfs_queue.pop()
145+
n_pops -= 1
146+
147+
dp_element = dp[curr_indexes[0]][curr_indexes[1]]
148+
dp_element[0] += distance # sum the distance from each building
149+
dp_element[1] += 1 # record how many buildings this land has reached
150+
151+
land_neighbors = self.get_land_neighbors(curr_indexes, grid)
152+
for neighbor in land_neighbors:
153+
if neighbor not in visited_set:
154+
visited_set.add(neighbor)
155+
bfs_queue.appendleft(neighbor)
156+
157+
def get_land_neighbors(self, indexes, grid):
158+
directions = [(0,-1),(1,0),(0,1),(-1,0)]
159+
results = list()
160+
for direction in directions:
161+
next_indexes = (indexes[0]+direction[0], indexes[1]+direction[1])
162+
if self.within_bounds(next_indexes, grid):
163+
element = grid[next_indexes[0]][next_indexes[1]]
164+
if element == 0:
165+
results.append(next_indexes)
166+
return results
167+
168+
def within_bounds(self, indexes, grid):
169+
row_i = indexes[0]
170+
col_i = indexes[1]
171+
if row_i >= 0 and col_i >= 0 and row_i < len(grid) and col_i < len(grid[0]):
172+
return True
173+
return False
174+
```

0 commit comments

Comments
 (0)