20
20
Expected result for K = 4: 6 (4 Stops: C0 --> C3 ---> C1 ---> C4 ---> C2)
21
21
22
22
2. Intuition:
23
- - Naive:
24
- - Kind of BFS + Optimizations: O(|V|^2 + |V||E|) ?
25
- - to have a variable dst cheapest path price (initialized to Infinity)
26
- - To visit cities multiple-times: when curr visit path price < prev visit path price
27
- - To stop a path if its price > dst cheapest path price
23
+ - Kind of BFS + Optimizations: O(|V|^2 + |V||E|) ?
24
+ - to have a variable dst cheapest path price (initialized to Infinity)
25
+ - To visit cities multiple-times: when curr visit path price < prev visit path price
26
+ - To stop a path if its price > dst cheapest path price
27
+ - DFS + memoization:
28
+ -
28
29
- We could do better:
29
30
30
31
3. Implementation
36
37
"""
37
38
from typing import List
38
39
39
- class Solution_BFS :
40
+ class Solution_Base :
41
+ def __init__ (self ):
42
+ self .__max_pirce = 10 ** 8
43
+
44
+ """
45
+ Time Complexity: O(|E|)
46
+ Space Complexity: O(|V| + |E|)
47
+ """
48
+ def __build_adjacency_list (self , cities_count : int , edges : List [List [int ]]) -> List [List [int ]]:
49
+
50
+ adjacency_list = [ [] for _ in range (cities_count ) ]
51
+ for [ source , sink , weight ] in edges :
52
+ adjacency_list [source ].append ([ sink , weight ])
53
+
54
+ return adjacency_list
55
+
56
+ def __indegree (self , v : int , edges : List [List [int ]]) -> int :
57
+ indegree = 0
58
+ for [ source , sink , weight ] in edges :
59
+ if sink == v :
60
+ indegree += 1
61
+
62
+ return indegree
63
+
64
+ class Solution_BFS (Solution_Base ):
40
65
'''
41
66
Time Complexity: O(|V|^2 + |V||E|) ?
42
67
T = T(Build Adjacency List) + T(Kind Of BFS algo)
@@ -51,6 +76,9 @@ def find_cheapest_price(self, cities_count: int, flights: List[List[int]], src:
51
76
52
77
adjacency_list = self .__build_adjacency_list (cities_count , flights )
53
78
79
+ if (self .__indegree (dst ) == 0 ):
80
+ return - 1
81
+
54
82
'''
55
83
Each node (city) is potentially visited multiple times.
56
84
Worst case:
@@ -86,22 +114,55 @@ def find_cheapest_price(self, cities_count: int, flights: List[List[int]], src:
86
114
87
115
return - 1 if cheapest_price == self .__max_pirce else cheapest_price
88
116
89
- class Solution_Base :
90
- def __init__ (self ):
91
- self .__max_pirce = 10 ** 8
92
-
93
- """
94
- Time Complexity: O(|E|)
95
- Space Complexity: O(|V| + |E|)
96
- """
97
- def __build_adjacency_list (self , cities_count : int , flights : List [List [int ]]) -> List [List [int ]]:
98
-
99
- adjacency_list = [ [] for _ in range (cities_count ) ]
100
- for [ flight_from , flight_to , flight_pirce ] in flights :
101
- adjacency_list [flight_from ].append ([ flight_to , flight_pirce ])
102
-
103
- return adjacency_list
117
+ class Solution_DFS (Solution_Base ):
118
+ '''
119
+ Time Complexity: O(K * |V|^2 + |E|)
120
+ T = T(Build Adjacency List) + T(DFS algo)
121
+ = O(|E|) + O(K * |V|^2)
122
+
123
+ Space Complexity: O(K * |V| + |E|)
124
+ S = S(Adjacency_list) + S(DFS)
125
+ = O(|V| + |E|) + O(K * |V|)
126
+
127
+ '''
128
+ def find_cheapest_price (self , cities_count : int , flights : List [List [int ]], src : int , dst : int , max_stops_count : int ) -> int :
129
+ adjacency_list = self .__build_adjacency_list (cities_count , flights )
104
130
131
+ if (self .__indegree (dst ) == 0 ):
132
+ return - 1
133
+
134
+ '''
135
+ Assumption: K < |V|
136
+ Time complexity:
137
+ depth Nbr of problems work at corresponding depth space at corresponding depth
138
+ 0 1 1 * O(outdegree(src)) = O(|V|) O(1)
139
+ 1 |V| |V| * O(|V|) = O(|V|^2) |V| * O(1)
140
+ ...
141
+ K |V| O(|V|^2) O(|V|)
142
+
143
+ Total time complexity: O(K * |V|^2)
144
+ Total space complexity: O(K * |V|)
145
+
146
+ '''
147
+ cheapest_price = self .__dfs (src , dst , adjacency_list , max_stops_count , {})
148
+ return - 1 if cheapest_price == self .__max_pirce else cheapest_price
149
+
150
+ def __dfs (self , src : int , dst : int , adjacency_list : List [List [int ]], remaining_stops_count : int , memo : dict ) -> int :
151
+ if src == dst :
152
+ return 0
153
+
154
+ if remaining_stops_count == - 1 :
155
+ return self .__max_pirce
156
+
157
+ elif (src , remaining_stops_count ) in memo :
158
+ return memo [(src , remaining_stops_count )]
159
+
160
+ cheapest_price = self .__max_pirce
161
+ for [ flight_to , flight_pirce ] in adjacency_list [src ]:
162
+ cheapest_price = min (cheapest_price , self .__dfs (flight_to , dst , adjacency_list , remaining_stops_count - 1 , memo ) + flight_pirce )
163
+
164
+ memo [(src , remaining_stops_count )] = cheapest_price
165
+ return cheapest_price
105
166
106
167
'''
107
168
4
0 commit comments