1
+ """
2
+ 1. Problem Summary / Clarifications / TDD:
3
+ 2. Inuition:
4
+ - Shortest path + all distances are positive
5
+ - Dijkstra's Algorithm
6
+ 3. Implementation:
7
+ 4. Complexity Analysis:
8
+ - Time Complexity: O(O((R + C) * R*C))?
9
+ - T(Initialization): O(R*C)
10
+ - T(heap.pop): O(R*C*logR*C)
11
+ - T(get_adjacency_list) = O((R + C) * R*C)
12
+ - T(heap.push): O(4*R*C*logR*C)
13
+ - Total: O(R*C) + O(R*C*logR*C) + O((R + C) * R*C) + O(4*R*C*logR*C)
14
+
15
+ """
16
+
17
+ import heapq
18
+
19
+ class Solution :
20
+
21
+ def __init__ (self ):
22
+ self .__empty = 0
23
+ self .__wall = 0
24
+
25
+ # Time Complexity: O(R*C) + O(R*C*log(R*C)) + O((R+C)R*Clog(R*C)) = O((R+C)R*Clog(R*C))
26
+ def shortestDistance (self , maze : List [List [int ]], start : List [int ], destination : List [int ]) -> int :
27
+
28
+ rows_count = len (maze )
29
+ cols_count = len (maze [0 ])
30
+
31
+ distances = [[10001 for _ in range (cols_count )] for _ in range (rows_count )]
32
+ distances [start [0 ]][start [1 ]] = 0
33
+
34
+ priority_q = [[0 , start [0 ], start [1 ]]]
35
+
36
+ while priority_q : # O(R*C)
37
+
38
+ position = heapq .heappop (priority_q ) # O(log(R*C))
39
+
40
+ for adjacent in self .__get_adjacency_list (maze , position ): # O(R + C)
41
+
42
+ if adjacent [0 ] < distances [adjacent [1 ]][adjacent [2 ]]:
43
+ distances [adjacent [1 ]][adjacent [2 ]] = adjacent [0 ]
44
+ heapq .heappush (priority_q , adjacent ) # O(log(R*C))
45
+
46
+ return - 1 if distances [ destination [0 ] ][ destination [1 ] ] == 10001 else distances [ destination [0 ] ][ destination [1 ] ]
47
+
48
+ # Time Complexity: O(rows + colums) = O(R + C)
49
+ # Space Complexity: O(4) = O(1)
50
+ def __get_adjacency_list (self , maze , position : List [int ]) -> List [List [int ]]:
51
+
52
+ adjacents = []
53
+
54
+ rows_count = len (maze )
55
+ cols_count = len (maze [0 ])
56
+
57
+ dist , row , col = position [0 ], position [1 ], position [2 ]
58
+
59
+ # Up
60
+ steps_count = 0
61
+ while row - steps_count and maze [row - steps_count - 1 ][col ] == self .__empty :
62
+ steps_count += 1
63
+ if steps_count :
64
+ adjacents .append ([dist + steps_count , row - steps_count , col ])
65
+
66
+ # Down
67
+ steps_count = 0
68
+ while row + steps_count + 1 < rows_count and maze [row + steps_count + 1 ][col ] == self .__empty :
69
+ steps_count += 1
70
+ if steps_count :
71
+ adjacents .append ([dist + steps_count , row + steps_count , col ])
72
+
73
+ # left
74
+ steps_count = 0
75
+ while col - steps_count and maze [row ][col - steps_count - 1 ] == self .__empty :
76
+ steps_count += 1
77
+ if steps_count :
78
+ adjacents .append ([dist + steps_count , row , col - steps_count ])
79
+
80
+ # Right
81
+ steps_count = 0
82
+ while col + steps_count + 1 < cols_count and maze [row ][col + steps_count + 1 ] == self .__empty :
83
+ steps_count += 1
84
+ if steps_count :
85
+ adjacents .append ([dist + steps_count , row , col + steps_count ])
86
+
87
+ return adjacents
0 commit comments