Bus Routes

HardGraph BFS · Hash Map Index🧩 Graph BFSLeetCode #815 ↗Updated

Problem

Each routes[i] lists the stops a bus loops through forever. You stand at stop source and want to reach stop target, moving only by bus. Return the fewest buses you must board, or -1 if the target is unreachable. Staying at source when it equals target costs 0 buses.
Inputroutes = [[1,2,7],[3,6,7]], source = 1, target = 6Output2
Inputroutes = [[7,12],[4,5,15],[6],[15,19],[9,12,13]], source = 15, target = 12Output-1
Inputroutes = [[1,2,3]], source = 2, target = 2Output0

1 ≤ routes.length ≤ 500  ·  1 ≤ routes[i].length ≤ 105  ·  stops within one route are distinct  ·  ∑ routes[i].length ≤ 105  ·  0 ≤ stops, source, target < 106

Try it yourself

Java
class Solution {
    public int numBusesToDestination(int[][] routes, int source, int target) {
        
    }
}
Your code is saved in this browser.Submit on LeetCode ↗
Key insight
We count buses, not stops, so a BFS level is “one more bus”. Index stop → routes, and once a route has been boarded never scan it again — every stop on it is already reachable at that bus count.
PatternGraph BFS

Instinct Minimum moves, fewest steps or shortest transformation where every step costs the same: spread outward level by level with a queue.

Memory hack Ripples in a pond: every ring is one step farther, so the first ring that touches the target is the answer.

Open the Graph BFS guide →

Approaches

Brute ForceRoute Graph via Pairwise Intersection

Time O(R²·L)Space O(R² + ∑L)

Make each route a node and connect two routes if they share any stop (test every pair with a hash set). BFS from all routes containing source with distance 1; the first popped route containing target gives the answer. L is the longest route.

Java
public int numBusesToDestination(int[][] routes, int source, int target) {
    if (source == target) return 0;
    int r = routes.length;
    List<Set<Integer>> stops = new ArrayList<>();
    for (int[] route : routes) {
        Set<Integer> s = new HashSet<>();
        for (int x : route) s.add(x);
        stops.add(s);
    }
    // two routes are linked if they share at least one stop
    List<List<Integer>> adj = new ArrayList<>();
    for (int i = 0; i < r; i++) adj.add(new ArrayList<>());
    for (int i = 0; i < r; i++) {
        for (int j = i + 1; j < r; j++) {
            for (int x : routes[i]) {
                if (stops.get(j).contains(x)) {
                    adj.get(i).add(j);
                    adj.get(j).add(i);
                    break;
                }
            }
        }
    }
    int[] dist = new int[r];
    Arrays.fill(dist, -1);
    Deque<Integer> queue = new ArrayDeque<>();
    for (int i = 0; i < r; i++) {
        if (stops.get(i).contains(source)) {
            dist[i] = 1;
            queue.offer(i);
        }
    }
    while (!queue.isEmpty()) {
        int cur = queue.poll();
        if (stops.get(cur).contains(target)) return dist[cur];
        for (int nxt : adj.get(cur)) {
            if (dist[nxt] == -1) {
                dist[nxt] = dist[cur] + 1;
                queue.offer(nxt);
            }
        }
    }
    return -1;
}

Correct and intuitive, but the all-pairs intersection step is quadratic in routes.

At a glance

LevelApproachTimeSpace
Brute ForceRoute Graph via Pairwise IntersectionO(R²·L)O(R² + ∑L)
BetterStop-Level BFS with a Stop → Routes IndexO(∑Li²)O(∑L)
OptimalStop-Level BFS + Boarded-Route MarkingO(∑L)O(∑L)
Common pitfalls
  • Forgetting source == target ⇒ 0, even when no route contains that stop.
  • Counting stops (edges between consecutive stops) instead of buses boarded.
  • Re-expanding the same route for every stop on it — quadratic on long routes.
Interview tips
  • Ask what a “move” costs: here it is a bus, which tells you what a BFS level means.
  • Contrast the stop graph (huge cliques) with the route graph (≤ 500 nodes).
  • Mention the stop → routes index as the key preprocessing step.
Pattern
BFS on a hyper-graph → when one action reaches a whole group of nodes, BFS over groups and mark each group used once.
My notes saved in this browser