leetcode 815. 公交路线

297 阅读1分钟

这是我参与更文挑战的第28天 ,活动详情查看更文挑战

题目

给你一个数组 routes ,表示一系列公交线路,其中每个 routes[i] 表示一条公交线路,第 i 辆公交车将会在上面循环行驶。

例如,路线 routes[0] = [1, 5, 7] 表示第 0 辆公交车会一直按序列 1 -> 5 -> 7 -> 1 -> 5 -> 7 -> 1 -> ... 这样的车站路线行驶。 现在从 source 车站出发(初始时不在公交车上),要前往 target 车站。 期间仅可乘坐公交车。

求出 最少乘坐的公交车数量 。如果不可能到达终点车站,返回 -1 。

 

示例 1:

输入:routes = [[1,2,7],[3,6,7]], source = 1, target = 6 输出:2 解释:最优策略是先乘坐第一辆公交车到达车站 7 , 然后换乘第二辆公交车到车站 6 。 示例 2:

输入:routes = [[7,12],[4,5,15],[6],[15,19],[9,12,13]], source = 15, target = 12 输出:-1  

提示:

1 <= routes.length <= 500. 1 <= routes[i].length <= 105 routes[i] 中的所有值 互不相同 sum(routes[i].length) <= 105 0 <= routes[i][j] < 106 0 <= source, target < 106

解题思路

使用两个map

  • 一个map用来完成站点对公车线路的映射(一个站点可能经过的多个站点)
  • 一个map用来完成公车对公车的映射(一路公车可以转乘的其他公车)

公车与公车之间的线路关系,就可以转化为一个双向的图,例如

[[1,2,7],[3,6,7]]
每一台公车作为一个节点,两路公共汽车具有相同的站点,公车之间就存在一条双向的边(因为公交车将会循环行驶,所以两台公车的站点是可以互相到达的)

因此对这个图进行广度优先搜索,就能得出从起点到终点的最短路径,就是最少乘坐的公交车数量

代码

class Solution {
 public int numBusesToDestination(int[][] routes, int source, int target) {
        if(source==target) return 0;
        HashSet<Integer> set = new HashSet<Integer>();

        Map<Integer, Set<Integer>>map=new HashMap<Integer,Set<Integer>>();
        //公车--》公车,公车
        Map<Integer,Set<Integer>> bus=new HashMap<Integer, Set<Integer>>();
        for (int j=0;j<routes.length;j++) {
            for (int i=0;i<routes[j].length;i++)
            {
                if(!map.containsKey(routes[j][i]))
                    map.put(routes[j][i],new HashSet<>());
                map.get(routes[j][i]).add(j);
            }
        }
        for (int j=0;j<routes.length;j++) {
            bus.put(j,new HashSet<>());
            for (int i=0;i<routes[j].length;i++)
            {
                bus.get(j).addAll(map.get(routes[j][i]));
            }
        }


        //

        int res=0;
        Queue<Integer>queue=new LinkedList<Integer>();
        for (Integer s : map.get(source)) {
            set.add(s);
            queue.add(s);
        }
        HashSet<Integer> su = new HashSet<Integer>();

        if(map.get(target)==null) return -1;
        for (Integer cur : map.get(target)) {
            su.add(cur);
        }

        while (!queue.isEmpty())
        {
            int size=queue.size();
            for (int i=0;i<size;i++)
            {
                Integer cur = queue.poll();
                if(su.contains(cur)) return res+1;
                Set<Integer> next = bus.get(cur);
                for (Integer th : next) {
                    if(!set.contains(th))
                        queue.add(th);
                    set.add(th);
                }
            }
            res++;
        }
        return -1;
    }
}