Cheapest Flights Within K Stops

There are n airports numbered 0 to n - 1. Each entry flights[i] = [from, to, price] is a one-way flight from airport from to airport to that costs price.

Find the lowest total price of a trip from src to dst that makes at most k stops. A stop is an intermediate airport where you change planes, so a trip with k stops uses at most k + 1 flights. If no such trip exists, return -1.

Example 1

Input: n = 4, flights = [[0,1,100],[1,2,100],[2,3,100],[0,3,500],[0,2,250]], src = 0, dst = 3, k = 1 Output: 350 Why: The cheapest route 0 → 1 → 2 → 3 costs 300 but needs 2 stops. With 1 stop allowed, 0 → 2 → 3 for 350 is the best.

Example 2

Input: n = 3, flights = [[0,1,40],[1,2,40],[0,2,100]], src = 0, dst = 2, k = 0 Output: 100 Why: With k = 0 only direct flights count, so the 100 ticket wins even though the route through airport 1 is cheaper.

Example 3

Input: n = 3, flights = [[0,1,5],[2,1,5]], src = 0, dst = 2, k = 1 Output: -1 Why: No flight ever leaves for airport 2, so it is unreachable.

Constraints

  • 2 <= n <= 100
  • 0 <= flights.length <= n * (n - 1) / 2
  • flights[i].length == 3
  • 0 <= from, to < n, from != to
  • 1 <= price <= 104
  • There is at most one flight between any ordered pair of airports.
  • 0 <= src, dst, k < n, src != dst

Pattern Path · Graphs: Traversal · problem 136 of 169

A plain shortest-path search ignores the stop limit. The cheapest way to reach an airport might use too many flights to continue from it.
Think in rounds: after round r, know the cheapest price to every airport using at most r flights. How do you get round r + 1 from round r?
Relax every flight once per round, but read prices from the previous round's array and write into a copy. Otherwise one round could chain several flights together. Run exactly k + 1 rounds.
Target: O(k · E) time, O(n) extra space.

Start simple

Enumerate every route of up to k + 1 flights with DFS and keep the cheapest: exponential, roughly O(n^(k+1)) in the worst case.

The key idea

The stop limit is really a limit on the number of flights: at most k + 1. That suggests building answers by flight count. Let cost[v] be the cheapest price to reach v using at most r flights. Initially (r = 0) only src is reachable, at price 0.

To go from r to r + 1 flights, try extending every known route by one flight: for each [u, v, p], the price cost[u] + p is a candidate for v. This is one round of the Bellman-Ford algorithm, capped at k + 1 rounds.

The key detail is to read from the previous round and write into a copy. If you update in place, a price you just lowered this round can be extended again in the same round, so one round might secretly use two or three flights and break the stop limit. With the copy, round r reflects exactly "at most r flights".

After k + 1 rounds, cost[dst] is the answer, or -1 if it is still infinite. Each round scans all E flights, so the total is O(k · E).

Complexity

  • Time: O(k · E)
  • Space: O(n)

Python

from math import inf


class Solution:
    def findCheapestPrice(self, n, flights, src, dst, k):
        # cost[v] = cheapest price to reach v using at most r flights (r = rounds so far).
        cost = [inf] * n
        cost[src] = 0

        for _ in range(k + 1):              # k stops means at most k + 1 flights
            next_cost = cost[:]             # read from the old round, write into a copy
            for u, v, price in flights:
                if cost[u] + price < next_cost[v]:
                    next_cost[v] = cost[u] + price
            cost = next_cost

        return -1 if cost[dst] == inf else cost[dst]

JavaScript

var findCheapestPrice = function(n, flights, src, dst, k) {
  // cost[v] = cheapest price to reach v using at most r flights (r = rounds so far).
  let cost = new Array(n).fill(Infinity);
  cost[src] = 0;

  for (let round = 0; round <= k; round++) {   // k stops means at most k + 1 flights
    const nextCost = cost.slice();             // read from the old round, write into a copy
    for (const [u, v, price] of flights) {
      if (cost[u] + price < nextCost[v]) nextCost[v] = cost[u] + price;
    }
    cost = nextCost;
  }

  return cost[dst] === Infinity ? -1 : cost[dst];
};

What the interviewer is checking

It tests whether you see why ordinary Dijkstra breaks under an extra constraint, and whether you can adapt a shortest-path algorithm by adding a dimension (here, flights used) to the state.

Mistakes to avoid

  • Running standard Dijkstra with a visited set: the cheapest way into an airport may use too many stops, and the slightly pricier way with fewer stops is then never explored.
  • Updating prices in place during a Bellman-Ford round, which lets one round use several flights.
  • Confusing stops with flights: k stops allows k + 1 flights.
  • Returning infinity instead of -1 when dst is unreachable.

Follow-ups to expect

  • Can you use a heap? (Dijkstra on (airport, stops) states.)
  • What if you also need the route itself? (Store a predecessor per round.)
  • What if prices could be negative? (Bellman-Ford rounds still work.)

In real software

Travel search engines and network routing protocols such as RIP compute cheapest paths under a hop limit; RIP literally runs distance-vector rounds and treats more than 15 hops as unreachable.

Practice next

Next Post Previous Post
No Comment
Add Comment
comment url