Cheapest Flight Within K Stops - LeetCode Daily Challenge
Problem Statement
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 = 8, flights = [[0,1,1],[0,5,5],[1,2,2],[2,3,1],[3,4,1],[4,6,6],[5,3,4],[5,7,2],[7,4,5]], src = 0, dst = 6, k = 3
Output: 16
Explanation:
The graph is shown above.
The optimal path with at most 3 stop from city 0 to 3 is 0 -> 5 -> 3 -> 4 -> 6 with minimum cost of 16.
Note that the path through cities [0,1,2,3,4,6] is cheaper but is invalid because it uses 4 stops.
Example 2
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 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.
Try here before watching the video.
Video Explanation
Java Code
class Pair {
int node, distance;
public Pair(int node, int distance) {
this.node = node;
this.distance = distance;
}
}
class Node {
int node, distance, stops;
public Node(int node, int distance, int stops) {
this.node = node;
this.distance = distance;
this.stops = stops;
}
}
class Solution {
private List<List<Pair>> buildGraph(int[][] flights, int n) {
List<List<Pair>> graph = new ArrayList<>();
for(int i = 0; i < n; i++) {
graph.add(new ArrayList<>());
}
for(int[] flight : flights) {
graph.get(flight[0]).add(new Pair(flight[1], flight[2]));
}
return graph;
}
public int findCheapestPrice(int n, int[][] flights, int src, int dst, int k) {
List<List<Pair>> graph = buildGraph(flights, n);
int[] distance = new int[n];
int[] stops = new int[n];
Arrays.fill(distance, Integer.MAX_VALUE);
Arrays.fill(stops, Integer.MAX_VALUE);
PriorityQueue<Node> minHeap = new PriorityQueue<>((node1, node2) -> node1.distance - node2.distance);
distance[src] = 0;
stops[src] = 0;
minHeap.add(new Node(src, distance[src], stops[src]));
while(!minHeap.isEmpty()) {
Node curr = minHeap.poll();
int currNode = curr.node;
int currDistance = curr.distance;
int currStops = curr.stops;
if(currNode == dst) return currDistance;
if(currStops == k + 1) continue;
for(Pair pair : graph.get(currNode)) {
int nbrNode = pair.node;
int nbrDistance = pair.distance;
if((currDistance + nbrDistance) < distance[nbrNode]) {
distance[nbrNode] = currDistance + nbrDistance;
stops[nbrNode] = currStops + 1;
minHeap.add(new Node(nbrNode, distance[nbrNode], stops[nbrNode]));
} else if((currStops + 1) < stops[nbrNode]) {
minHeap.add(new Node(nbrNode, currDistance + nbrDistance, currStops + 1));
}
}
}
return -1;
}
}
C++ Code
class Node {
public:
int node, distance, stops;
Node(int node, int distance, int stops) {
this->node = node;
this->distance = distance;
this->stops = stops;
}
};
class Solution {
public:
struct comparator {
bool operator() (Node a, Node b) {
return a.distance > b.distance;
}
};
vector<vector<pair<int, int>>> buildGraph(int n, vector<vector<int>>& flights) {
vector<vector<pair<int, int>>> graph;
for(int i = 0; i < n; i++) {
vector<pair<int, int>> v;
graph.push_back(v);
}
for(auto flight : flights) {
graph[flight[0]].push_back(make_pair(flight[1], flight[2]));
}
return graph;
}
int findCheapestPrice(int n, vector<vector<int>>& flights, int src, int dst, int k) {
vector<vector<pair<int, int>>> graph = buildGraph(n, flights);
priority_queue<Node, vector<Node>, comparator> minHeap;
vector<int> distance(n, INT_MAX);
vector<int> stops(n, INT_MAX);
distance[src] = 0;
stops[src] = 0;
minHeap.push(Node(src, 0, 0));
while(!minHeap.empty()) {
Node curr = minHeap.top();
minHeap.pop();
int currNode = curr.node;
int currDistance = curr.distance;
int currStops = curr.stops;
if(currNode == dst) return currDistance;
if(currStops == k + 1) continue;
for(auto pair : graph[currNode]) {
int nbrNode = pair.first;
int nbrDistance = pair.second;
if(currDistance + nbrDistance < distance[nbrNode]) {
distance[nbrNode] = currDistance + nbrDistance;
stops[nbrNode] = currStops + 1;
minHeap.push(Node(nbrNode, distance[nbrNode], stops[nbrNode]));
} else if(currStops + 1 < stops[nbrNode]) {
minHeap.push(Node(nbrNode, currDistance + nbrDistance, currStops + 1));
}
}
}
return -1;
}
};
Python Code
class Solution:
def build_graph(n, flights):
graph = []
for i in range(n):
graph.append(list()) # graph = [[], [], [], [], []]
for flight in flights:
graph[flight[0]].append((flight[1], flight[2]))
return graph
def findCheapestPrice(self, n: int, flights: List[List[int]], src: int, dst: int, k: int) -> int:
graph = Solution.build_graph(n, flights)
min_heap = []
distance = [math.inf] * n
stops = [math.inf] * n
distance[src] = 0
stops[src] = 0
heappush(min_heap, (0, 0, src))
while min_heap:
curr_dist, curr_stop, curr_node = heappop(min_heap)
if curr_node == dst:
return curr_dist
if curr_stop == k + 1:
continue
for nbr, dist in graph[curr_node]:
if curr_dist + dist < distance[nbr]:
distance[nbr] = curr_dist + dist
stops[nbr] = curr_stop + 1
heappush(min_heap, (distance[nbr], stops[nbr], nbr))
elif curr_stop + 1 < stops[nbr]:
heappush(min_heap, (curr_dist + dist, curr_stop + 1, nbr))
return -1
Go Code
type Pair struct {
node int
distance int
}
type Node struct {
node int
distance int
stops int
}
type MinHeap []Node
func (h MinHeap) Len() int { return len(h) }
func (h MinHeap) Less(i, j int) bool { return h[i].distance < h[j].distance }
func (h MinHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] }
func (h *MinHeap) Push(x interface{}) {
*h = append(*h, x.(Node))
}
func (h *MinHeap) Pop() interface{} {
old := *h
n := len(old)
item := old[n-1]
*h = old[0 : n-1]
return item
}
func buildGraph(n int, flights [][]int) [][]Pair {
graph := make([][]Pair, n)
for _, flight := range flights {
start, end, distance := flight[0], flight[1], flight[2]
graph[start] = append(graph[start], Pair{end, distance})
}
return graph
}
func findCheapestPrice(n int, flights [][]int, src int, dst int, k int) int {
graph := buildGraph(n, flights)
distance := make([]int, n)
stops := make([]int, n)
for i := range distance {
distance[i] = int(1e9)
stops[i] = int(1e9)
}
minHeap := &MinHeap{}
heap.Init(minHeap)
distance[src] = 0
stops[src] = 0
heap.Push(minHeap, Node{src, distance[src], stops[src]})
for minHeap.Len() > 0 {
curr := heap.Pop(minHeap).(Node)
currNode := curr.node
currDistance := curr.distance
currStops := curr.stops
if currNode == dst {
return currDistance
}
if currStops == k+1 {
continue
}
for _, pair := range graph[currNode] {
nbrNode := pair.node
nbrDistance := pair.distance
newDistance := currDistance + nbrDistance
newStops := currStops + 1
if newDistance < distance[nbrNode] {
distance[nbrNode] = newDistance
stops[nbrNode] = newStops
heap.Push(minHeap, Node{nbrNode, newDistance, newStops})
} else if newStops < stops[nbrNode] {
heap.Push(minHeap, Node{nbrNode, newDistance, newStops})
}
}
}
return -1
}
Complexity Analysis
Time Complexity: O(V log V)
Space Complexity: O(E + V), where E is the number of edges and V is the number of vertices.