这道题虽然是hard, 但是思路比较直接。首先要看到这是一个graph的问题,连通的节点不是bus stop,而是bus/route。

  • 对每一个bus route建立stop map或set,方便以后查询
  • 利用前一步的stop map, 两两比较bus route,确定是否两个route之间有相同的stop,如果有则这两个routes是连通的
  • 对起点和终点找到所有bus routes包含起点或终点
  • 以所有包括起点的bus routes开始进行bfs,当某个route在终点所包括的routes中,返回当前的level
var numBusesToDestination = function(routes, S, T) {
    const numBuses = routes.length;
    if (numBuses === 0) {
        return -1;
    }
    if (S === T) {
        return 0;
    }
    const stops = [];
    for (let i = 0; i < numBuses; i++) {
        const map = {};
        const route = routes[i];
        for (let j = 0; j < route.length; j++) {
            map[route[j]] = true;
        }
        stops.push(map);
    }

    const connection = {};
    for (let i = 0; i < numBuses; i++) {
        connection[i] = [];
    }
    for (let i = 0; i < numBuses; i++) {
        for (let j = i+1; j < numBuses; j++) {
            if (hasConnection(stops[i], stops[j])) {
                connection[i].push(j);
                connection[j].push(i);
            }            
        }
    }

    // find which routes include start and end
    const routesIncludeStartList = [...findStopFromRoutes(stops, S)];
    const routesIncludeEndSet = findStopFromRoutes(stops, T);

    const queue = routesIncludeStartList;
    let level = 1;
    const visited = new Set();
    while (queue.length > 0) {
        const size = queue.length;
        for (let i = 0; i < size; i++) {
            const curr = queue.pop();
            if (routesIncludeEndSet.has(curr)) {
                return level;
            }
            for (let j = 0; j < connection[curr].length; j++) {
                if (!visited.has(connection[curr][j])) {
                    visited.add(connection[curr][j]);
                    queue.unshift(connection[curr][j]);
                }
            }
        }
        level++;
    }
    return -1;
};

function findStopFromRoutes(stops, S) {
    const res = new Set();
    for (let i = 0; i < stops.length; i++) {
        const routeMap = stops[i];
        if (S in routeMap) {
            res.add(i);
        }
    }
    return res;
}

function hasConnection(map1, map2) {
    for (let key in map1) {
        if (key in map2) {
            return true;
        }
    }
    return false;
}

results matching ""

    No results matching ""