LeetCode 815. Bus Routes

You are given an array routes representing bus routes where routes[i] is a bus route that the ith bus repeats forever.

  • For example, if routes[0] = [1, 5, 7], this means that the 0th bus travels in the sequence 1 -> 5 -> 7 -> 1 -> 5 -> 7 -> 1 -> ... forever.

You will start at the bus stop source (You are not on any bus initially), and you want to go to the bus stop target. You can travel between bus stops by buses only.

Return the least number of buses you must take to travel from source to target. Return -1 if it is not possible.

Example 1:

Input: routes = [[1,2,7],[3,6,7]], source = 1, target = 6
Output: 2
Explanation: The best strategy is take the first bus to the bus stop 7, then take the second bus to the bus stop 6.

Example 2:

Input: routes = [[7,12],[4,5,15],[6],[15,19],[9,12,13]], source = 15, target = 12
Output: -1

Constraints:

  • 1 <= routes.length <= 500.
  • 1 <= routes[i].length <= 105
  • All the values of routes[i] are unique.
  • sum(routes[i].length) <= 105
  • 0 <= routes[i][j] < 106
  • 0 <= source, target < 106

BFS的hard题,几百年没做过BFS了不会,复习完BFS还是不会,啊。

这题首先需要考虑怎么去构造这个可以用来BFS的数据结构。题目给的是每个route里有哪些stop,但是我们需要知道的是stop怎么去找下一个stop,所以刚开始我的想法就是构造一个map,key是stop,value是a list of next stops。这样的想法其实也是可以的,但是在stops巨多的情况下就很容易TLE了(抄完答案回来改这个做法以后发现其实是work的,但是submit的时候在一个有9w个stop要求从0到9w的case TLE了)。抄答案的做法构造的是stop到经过它的route的index的map,这就显然比记录所有next stop要lightweight很多。有一个语法上的小技巧,就是在构造这个Map<Integer, List<Integer>>的时候,想要往list里加东西可以不需要重新put一个list进去,而可以直接get().add()来操作这个list。

构造完数据结构以后就是常规BFS了。需要考虑这个queue里放什么。很直观应该用stop,但是因为前面构造的map是to route的所以刚开始被confuse到了,其实还是应该是a queue of stop。常规先把source加进queue,while queue is not empty,get size of queue,然后for loop for each element in the queue,这个for loop里面就要看看这个stop能去哪些route,如果这些route里有target那就可以快乐return 层数which is result了。不然就把这些stop都pop进queue,下一层再来看看。

还有一个点就是还需要用一个visited set来存放已经visited的route,不然就会死循环?

最后就是一些corner case,比如source == target的时候,进到我们的循环里以后会return result + 1就会是1,所以需要拎出来单独处理。

class Solution {
    public int numBusesToDestination(int[][] routes, int source, int target) {
        // we need to deal with this case explicity
        if (source == target) {
            return 0;
        }

        // store each stop and the bus route index that stops at the stop
        Map<Integer, List<Integer>> stopToRoutes = new HashMap<>();
        for (int i = 0; i < routes.length; i++) {
            for (int stop : routes[i]) {
                stopToRoutes.putIfAbsent(stop, new ArrayList<>());
                stopToRoutes.get(stop).add(i);
            }
        }

        // BFS to iterate through all the routes
        int result = 0;
        Queue<Integer> stopQueue = new ArrayDeque<>();
        Set<Integer> visitedRoute = new HashSet<>();
        stopQueue.add(source);
        while (!stopQueue.isEmpty()) {
            int size = stopQueue.size();
            for (int i = 0; i < size; i++) {
                int currStop = stopQueue.remove();
                // need to deal with the case when there is no route from the source explicitly
                // otherwise the get(stop) will be null
                List<Integer> canGoToRoute = stopToRoutes.getOrDefault(currStop, new ArrayList<>());
                for (int route : canGoToRoute) {
                    // don't want to visit the same route again
                    if (visitedRoute.contains(route)) {
                        continue;
                    }
                    visitedRoute.add(route);
                    for (int stop : routes[route]) {
                        if (stop == target) {
                            return result + 1;
                        }
                        stopQueue.add(stop);
                    }
                }
            }
            result++;
        }
        return -1;
    }
}

  • 16
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值