There are n
cities connected by some number of flights. You are given an array flights
where flights[i] = [fromi, toi, pricei]
indicates that there is a flight from city fromi
to city toi
with cost pricei
.
You are also given three integers src
, dst
, and k
, return the cheapest price from src
to dst
with at most k
stops. If there is no such route, return -1
.
Example 1:
Input: n = 4, flights = [[0,1,100],[1,2,100],[2,0,100],[1,3,600],[2,3,200]], src = 0, dst = 3, k = 1 Output: 700 Explanation: The graph is shown above. The optimal path with at most 1 stop from city 0 to 3 is marked in red and has cost 100 + 600 = 700. Note that the path through cities [0,1,2,3] is cheaper but is invalid because it uses 2 stops.
Example 2:
Input: n = 3, flights = [[0,1,100],[1,2,100],[0,2,500]], src = 0, dst = 2, k = 1 Output: 200 Explanation: The graph is shown above. The optimal path with at most 1 stop from city 0 to 2 is marked in red and has cost 100 + 100 = 200.
Example 3:
Input: n = 3, flights = [[0,1,100],[1,2,100],[0,2,500]], src = 0, dst = 2, k = 0 Output: 500 Explanation: The graph is shown above. The optimal path with no stops from city 0 to 2 is marked in red and has cost 500.
Constraints:
1 <= n <= 100
0 <= flights.length <= (n * (n - 1) / 2)
flights[i].length == 3
0 <= fromi, toi < n
fromi != toi
1 <= pricei <= 104
0 <= src, dst, k < n
src != dst
When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
We want to find the cheapest flight route from a starting city to a destination city, with a limit on the number of connecting flights. The brute force approach explores every possible flight path to find the cheapest one that meets our requirements.
Here's how the algorithm would work step-by-step:
def find_cheapest_flights_brute_force(number_of_cities, flights, source, destination, max_stops):
cheapest_price = float('inf')
def depth_first_search(current_city, stops_remaining, current_cost, visited):
nonlocal cheapest_price
if current_city == destination:
cheapest_price = min(cheapest_price, current_cost)
return
if stops_remaining < 0:
return
# Need to check for cycles to avoid infinite recursion
if current_city in visited:
return
visited.add(current_city)
for start_city, end_city, price in flights:
if start_city == current_city:
# Explore the next city with reduced stops and increased cost
depth_first_search(end_city, stops_remaining - 1, current_cost + price, visited.copy())
visited.remove(current_city)
# Initialize the depth first search to find the min price
depth_first_search(source, max_stops, 0, set())
if cheapest_price == float('inf'):
return -1
else:
return cheapest_price
To find the cheapest flight with a limited number of stops, we explore possible routes step-by-step, always tracking the lowest price we've found so far for each city after a certain number of stops. We use this information to intelligently discard routes that are already more expensive than known cheaper options.
Here's how the algorithm would work step-by-step:
def find_cheapest_price(number_of_cities, flights, source_city, destination_city, max_stops):
cheapest_prices = {}
cheapest_prices[source_city] = 0
for current_stop in range(max_stops + 1):
temp_cheapest_prices = cheapest_prices.copy()
for start_city, end_city, price in flights:
if start_city in cheapest_prices:
# Only process flights departing from reached cities.
current_price = cheapest_prices[start_city] + price
if end_city not in temp_cheapest_prices or current_price < temp_cheapest_prices[end_city]:
# Found a cheaper route to the destination.
temp_cheapest_prices[end_city] = current_price
cheapest_prices = temp_cheapest_prices
# Return the cheapest price if found.
if destination_city in cheapest_prices:
return cheapest_prices[destination_city]
else:
return -1
Case | How to Handle |
---|---|
flights is null or empty | If flights is null or empty, and src != dst return -1, else if flights is null or empty and src == dst return 0. |
n is zero or negative | If n is non-positive, there can be no valid path, return -1. |
k is negative | If k is negative, it is an invalid input, return -1. |
src is equal to dst | If src is equal to dst, the cost is 0 regardless of the number of stops, so return 0. |
No path exists from src to dst within k stops | If after exploring all possible paths within k stops, dst is not reached, return -1. |
Integer overflow during price calculation | Use long data type to store prices during calculation and before returning, or check if the running total exceeds a maximum amount (like Integer.MAX_VALUE). |
Graph contains cycles | The BFS/Bellman-Ford algorithm naturally handles cycles by tracking the number of stops/iterations and ensuring it doesn't exceed k. |
Maximum values for n, k and prices that could lead to TLE (Time Limit Exceeded) | Optimize the algorithm to use Dijkstra or Bellman-Ford with efficient priority queue or early stopping conditions to avoid unnecessary computations. |