1+ /**
2+ * Question Link: https://leetcode.com/problems/shortest-distance-from-all-buildings
3+ * Primary idea: Use BFS to caculate distance from building to all valid points, and
4+ * then figuare out the smallest one of all candidates
5+ *
6+ * Time Complexity: O((mn)^2), Space Complexity: O(mn)
7+ *
8+ */
9+
10+ class ShortestDistanceAllBuildings {
11+ func shortestDistance( _ grid: [ [ Int ] ] ) -> Int {
12+ guard grid. count > 0 && grid [ 0 ] . count > 0 else {
13+ return - 1
14+ }
15+
16+ let m = grid. count, n = grid [ 0 ] . count
17+ var distances = Array ( repeating: Array ( repeating: 0 , count: n) , count: m) , reachableNums = Array ( repeating: Array ( repeating: 0 , count: n) , count: m)
18+ var shortestDistance = Int . max, buildingNums = 0
19+
20+ for i in 0 ..< m {
21+ for j in 0 ..< n {
22+ if grid [ i] [ j] == 1 {
23+ buildingNums += 1
24+ bfs ( grid, & distances, & reachableNums, i, j)
25+ }
26+ }
27+ }
28+
29+ for i in 0 ..< m {
30+ for j in 0 ..< n {
31+ if reachableNums [ i] [ j] == buildingNums {
32+ shortestDistance = min ( shortestDistance, distances [ i] [ j] )
33+ }
34+ }
35+ }
36+
37+ return shortestDistance == Int . max ? - 1 : shortestDistance
38+ }
39+
40+ fileprivate func bfs( _ grid: [ [ Int ] ] , _ distances: inout [ [ Int ] ] , _ reachableNums: inout [ [ Int ] ] , _ i: Int , _ j: Int ) {
41+ let m = grid. count, n = grid [ 0 ] . count
42+ var pointsQueue = [ ( i, j) ] , distancesQueue = [ 0 ]
43+ var visited = Array ( repeating: Array ( repeating: false , count: n) , count: m)
44+
45+ while !pointsQueue. isEmpty {
46+ let currentPoint = pointsQueue. removeFirst ( ) , x = currentPoint. 0 , y = currentPoint. 1
47+ let currentDistance = distancesQueue. removeFirst ( )
48+ let ranges = [ ( x + 1 , y) , ( x - 1 , y) , ( x, y + 1 ) , ( x, y - 1 ) ]
49+
50+ // set distances and reachableNums
51+ if grid [ x] [ y] == 0 {
52+ distances [ x] [ y] += currentDistance
53+ reachableNums [ x] [ y] += 1
54+ }
55+
56+ // search neighbors
57+ for range in ranges {
58+ let xx = range. 0 , yy = range. 1
59+
60+ guard xx >= 0 && xx < m && yy >= 0 && yy < n && !visited[ xx] [ yy] else {
61+ continue
62+ }
63+
64+ guard grid [ xx] [ yy] == 0 else {
65+ continue
66+ }
67+
68+ visited [ xx] [ yy] = true
69+ pointsQueue. append ( ( xx, yy) )
70+ distancesQueue. append ( currentDistance + 1 )
71+ }
72+ }
73+ }
74+ }
0 commit comments