Bus Routes

Solution For Bus Routes

The Bus Routes problem on Leetcode asks us to find the minimum numbers of bus we need to take to reach our destination, given the list of bus routes available and the stops they can make.

The problem can be solved using Breadth First Search (BFS) and Graph theory concepts.

Approach:
1. Create a graph where each bus stop is represented as a node and edges are drawn between two bus stops if they are covered by the same bus route. Thus, given a list of bus routes and the stops they can make, we can create a graph with this information.
2. Start BFS from the source bus stop and keep adding stops covered by the same bus route to a queue and process them till we reach the destination stop.
3. Keep track of the number of bus we take to reach the destination stop and return the minimum number.

Detailed Solution:

  1. Create a Graph:
    To create a graph, we can use a dictionary where the key represents a bus stop and the value is a list of bus routes that cover that bus stop. We can iterate through each bus route and add its stops to the graph.
    Code:
    from collections import defaultdict
    def createGraph(routes):
    graph = defaultdict(list)
    for i, route in enumerate(routes):
    for stop in route:
    graph[stop].append(i)
    return graph

    The created graph would look like:
    {
    1: [0, 1],
    2: [0],
    3: [1, 2],
    4: [2] }

    where,
  2. node 1 is covered by bus routes 0 and 1
  3. node 2 is covered by bus route 0
  4. node 3 is covered by bus routes 1 and 2
  5. node 4 is covered by bus route 2

  6. BFS:
    To perform BFS, we can start at source bus stop and add its neighbouring stops that are covered by the same bus route. We can keep a visited set to store the visited stops to avoid processing them again. We need to make sure that we are not iterating through the same bus route again and again as we can take that bus route only once during our journey. Therefore, we can use a set to keep track of bus routes that we have already taken. We can stop once we reach our destination bus stop.
    Code:
    def bfs(graph, start, end, routes):
    queue = [(start, 0)] visited = set()
    busTaken = set()
    while queue:
    busStop, busCount = queue.pop(0)
    if busStop == end:
    return busCount
    for busRoute in graph[busStop]:
    if busRoute not in busTaken:
    busTaken.add(busRoute)
    for stop in routes[busRoute]:
    if stop not in visited:
    visited.add(stop)
    queue.append((stop, busCount+1))
    return -1

  7. Main:
    Now, we include both functions and take input to get the minimum number of buses needed.
    Code:
    class Solution:
    def numBusesToDestination(self, routes: List[List[int]], source: int, target: int) -> int:
    graph = createGraph(routes)
    return bfs(graph, source, target, routes)

    The overall time complexity of this solution is O(NM), where N is the number of bus routes and M is the average number of bus stops covered by each route. The space complexity is O(NM) as we are creating a graph of all nodes and edges.

Thus, we can get the minimum number of buses needed to reach the destination given a set of bus routes and the stops that they cover.

Step by Step Implementation For Bus Routes

class Solution {
    public boolean busRoutes(int[][] routes, int S, int T) {
        // Create a map of bus stops to the buses that go through them
        Map> stopsToBuses = new HashMap<>();
        for (int i = 0; i < routes.length; i++) {
            for (int j = 0; j < routes[i].length; j++) {
                stopsToBuses.computeIfAbsent(routes[i][j], k -> new HashSet<>()).add(i);
            }
        }
        
        // Perform a BFS from S to T, keeping track of which buses we've visited
        Queue queue = new LinkedList<>();
        Set visitedBuses = new HashSet<>();
        queue.add(S);
        while (!queue.isEmpty()) {
            int stop = queue.poll();
            if (stop == T) {
                return true;
            }
            for (int bus : stopsToBuses.getOrDefault(stop, new HashSet<>())) {
                if (visitedBuses.contains(bus)) {
                    continue;
                }
                visitedBuses.add(bus);
                for (int nextStop : routes[bus]) {
                    if (nextStop == stop) {
                        continue;
                    }
                    queue.add(nextStop);
                }
            }
        }
        return false;
    }
}
# here we are given a list of bus routes, where each bus route is # represented as a list of integers. We are also given a start # node S and an end node T. We are to find the shortest route # from S to T. def find_shortest_route(bus_routes, S, T): # we will use a breadth-first search to find the shortest route # from S to T. We will keep track of which nodes we have visited # in a set, and we will also keep track of the length of the # shortest route from S to each node in a dictionary. visited = set() route_lengths = {} # we will start by enqueuing S onto our queue, and setting the # length of the shortest route from S to S to be 0. queue = [S] route_lengths[S] = 0 # now we will keep processing nodes from the queue until we # either find T (in which case we are done) or we run out of # nodes (in which case there is no route from S to T) while queue: # dequeue the first node from the queue node = queue.pop(0) # if we have found T, we are done if node == T: return route_lengths[node] # otherwise, mark the node as visited and process each of its # neighbors for neighbor in bus_routes[node]: if neighbor not in visited: # enqueue the neighbor onto the queue queue.append(neighbor) # update the length of the shortest route from S to the # neighbor in the dictionary route_lengths[neighbor] = route_lengths[node] + 1 # mark the neighbor as visited visited.add(neighbor) # if we get to this point, it means we have processed all the # nodes and we have not found T, so there is no route from S to T return -1
var busRoutes = function(routes, S, T) {
    if (S === T) return 0;
    
    const map = new Map();
    for (let i = 0; i < routes.length; i++) {
        for (let j = 0; j < routes[i].length; j++) {
            if (!map.has(routes[i][j])) {
                map.set(routes[i][j], [i]);
            } else {
                const arr = map.get(routes[i][j]);
                arr.push(i);
                map.set(routes[i][j], arr);
            }
        }
    }
    
    if (!map.has(S) || !map.has(T)) return -1;
    
    const queue = [];
    const visited = new Set();
    queue.push(S);
    visited.add(S);
    
    let level = 0;
    while (queue.length > 0) {
        const size = queue.length;
        for (let i = 0; i < size; i++) {
            const stop = queue.shift();
            const busNumbers = map.get(stop);
            for (let j = 0; j < busNumbers.length; j++) {
                const route = routes[busNumbers[j]];
                for (let k = 0; k < route.length; k++) {
                    if (visited.has(route[k])) continue;
                    if (route[k] === T) return level + 1;
                    queue.push(route[k]);
                    visited.add(route[k]);
                }
            }
        }
        level++;
    }
    
    return -1;
};
We can solve this problem using a graph. We can create a graph where the nodes are the bus stops and the edges are the bus routes. Then, we can use a breadth-first search algorithm to find the shortest path from the starting node to the ending node.

Here is the pseudocode for the algorithm:

function findShortestPath(graph, start, end):
    // create an empty queue
    queue = []

    // create a set to keep track of visited nodes
    visited = set()

    // add the starting node to the queue
    queue.append(start)

    // while the queue is not empty
    while queue:
        // get the first node in the queue
        node = queue.pop(0)

        // if the node is the end node, we are done
        if node == end:
            return node

        // if the node is not in the visited set, mark it as visited
        if node not in visited:
            visited.add(node)

            // add all of the node's neighbors to the queue
            for neighbor in graph[node]:
                queue.append(neighbor)

    // if we get here, then there is no path from the start node to the end node
    return -1
using System; 
using System.Collections.Generic; 
using System.Linq; 

public class Solution { 
    public int NumBusesToDestination(int[][] routes, int S, int T) { 
        if (S == T) return 0; 
        
        // key: stop, value: the buses can go through this stop 
        var map = new Dictionary>(); 
        for (int i = 0; i < routes.Length; i++) { 
            foreach (var j in routes[i]) { 
                if (!map.ContainsKey(j)) { 
                    map[j] = new HashSet(); 
                } 
                map[j].Add(i); 
            } 
        } 
        
        var visited = new HashSet(); 
        var queue = new Queue(); 
        queue.Enqueue(S); 
        visited.Add(S); 
        int count = 0; 
        
        while (queue.Count != 0) { 
            count++; 
            int size = queue.Count; 
            for (int i = 0; i < size; i++) { 
                var cur = queue.Dequeue(); 
                foreach (var bus in map[cur]) { 
                    foreach (var next in routes[bus]) { 
                        if (next == T) return count; 
                        if (visited.Contains(next)) continue; 
                        visited.Add(next); 
                        queue.Enqueue(next); 
                    } 
                } 
            } 
        } 
        
        return -1; 
    } 
}


Scroll to Top
[gravityforms id="5" description="false" titla="false" ajax="true"]