Leetcode 787. Cheapest Flights Within K Stops
You are given a series of flights 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. You need to find the cheapest price from the city src to the city dst with at most k stops. If there is no such route, return -1.
n = 3, flights = [[0,1,100],[1,2,100],[0,2,500]], src = 0, dst = 2, k = 1200n = 3, flights = [[0,1,100],[1,2,100],[0,2,500]], src = 0, dst = 2, k = 0500Q: Can cities be revisited? A: No, the same city cannot be revisited according to constraints of cycles in Dijkstra’s algorithm.
Q: Are there any limits on the number of cities or flights?
A: The constraints typically are given in the full problem statement on LeetCode. However, for optimal implementation, we can generally expect n and flights to be reasonably large but within computational limit for algorithms like DFS, BFS, or Dijkstra’s with priority queue.
Q: Is the graph directed or undirected?
A: The graph representing flights is a directed graph because a flight from A to B does not imply a flight from B to A.
We can approach this problem using a modified Dijkstra’s algorithm with a priority queue (min-heap). The priority queue will help efficiently fetch the current minimum cost route. Additionally, tracking the number of stops helps ensure the k stop condition is met.
flights.(cost, current_city, stops).(0, src, 0) into the priority queue.k + 1, push all neighboring cities into the priority queue with updated costs and stops.k stops, return -1.#include <vector>
#include <queue>
#include <unordered_map>
#include <tuple>
using namespace std;
int findCheapestPrice(int n, vector<vector<int>>& flights, int src, int dst, int k) {
// Create the adjacency list
unordered_map<int, vector<pair<int, int>>> graph;
for (const auto& flight : flights) {
graph[flight[0]].emplace_back(flight[1], flight[2]);
}
// Priority queue: (cost, current_node, stops)
priority_queue<tuple<int, int, int>, vector<tuple<int, int, int>>, greater<>> pq;
pq.emplace(0, src, 0);
// Vector to track minimum cost to reach each city with a given number of stops
vector<vector<int>> min_cost(n, vector<int>(k + 2, INT_MAX));
min_cost[src][0] = 0;
while (!pq.empty()) {
auto [cost, curr_city, stops] = pq.top();
pq.pop();
if (curr_city == dst) return cost;
// If we have more stops available
if (stops <= k) {
for (const auto& [neighbor, price] : graph[curr_city]) {
int new_cost = cost + price;
// If we find a cheaper cost path or if we're visiting the neighbor with fewer stops.
if (new_cost < min_cost[neighbor][stops + 1]) {
min_cost[neighbor][stops + 1] = new_cost;
pq.emplace(new_cost, neighbor, stops + 1);
}
}
}
}
return -1;
}
O(E), where E is the number of edges (flights).push and pop operation in the priority queue is O(log(V + E)). Over the entire algorithm, this results in O((V + E) log(V + E)).Overall, the time complexity is O((V + E) log(V + E)), making the solution efficient even for relatively large inputs.
Got blindsided by a question you didn’t expect?
Spend too much time studying?
Or simply don’t have the time to go over all 3000 questions?