输入:int[][] routes routes[i]表示第i号公交车的运行线路。如果routes[i]={1,3,5}。说明公交车运行线路是1->3->5。
int S:表示起始站点
int T:表示目的站点
输出:从S到T最少需要几辆公交车。
规则:一开始人没有坐在公交车上,出行方式只用公交车。
分析:很自然的想到以各个站点为节点,站点之间从上一站到下一站作为线。每个站点添加个list维护这个站点属于哪些公交车。
这样的想法很自然,很惯性,确没有什么用。因为要找的是公交车数量的最小值,所以应该重点关注如何从一个公交车跳转到另外一个公交车。直到调到包含T的公交车上。
学习1:官方的solution
把公交车看做是图的节点。要返回最少的公交车数量,就是一个最短路径问题。
如果两个公交车至少有一个站是相同的,那这两个公交车之间有连线。
从起始站开始BFS遍历图,直到遇到目标站。
一个站可能在多个公交车里面有,所以起始队列和终点目标都是多个的。
这里发现BFS总能解决最短路径问题。;例如847,也是最短路径,也用了BFS。
public int numBusesToDestination(int[][] routes, int S, int T) {//构建图Map<Integer, List<Integer>> graph = new HashMap<Integer,List<Integer>>();int N = routes.length;for(int i=0;i<N;i++){Arrays.sort(routes[i]);graph.put(i,new ArrayList<Integer>());}for(int i=0;i<N;i++){for(int j = i+1;j<N;j++){if(intersection(routes[i],routes[j])){graph.get(i).add(j);graph.get(j).add(i);}}}//遍历Queue<Point> queue = new ArrayDeque<>();Set<Integer> seen = new HashSet<>();List<Integer> targets = new ArrayList<>();for(int i=0;i<N;i++){if(Arrays.binarySearch(routes[i],S)!=-1){queue.offer(new Point(i,0));seen.add(i);}if(Arrays.binarySearch(routes[i],T)!=-1){targets.add(i);}}while(!queue.isEmpty()){Point point = queue.poll();int node = point.x;int depth = point.y;if(targets.contains(node)){return depth+1;}else{for(Integer next : graph.get(node)){if(!seen.contains(next)){seen.add(next);queue.offer(new Point(next,depth+1));}}}}return -1;}/*** 判断两个数组是否有交集* @param a* @param b* @return*/private boolean intersection(int[] a,int[] b) {int i = 0;int j = 0;while(i<a.length && j<b.length){if(a[i]==b[j]) return true;if(a[i]<b[j]){i++;}else{j++;}}return false;}
学习2:如果把公交站点看做图中的节点也是可以的。但是不是以公交车的线路作为连线的。而是一次访问了一辆公交车上所有的站点。理解起来不如上面的解法。
/*** https://leetcode.com/problems/bus-routes/discuss/122712/Simple-Java-Solution-using-BFS* 我一定认为要按照公交车的行驶顺利遍历站点。* 如果roets[0]={1,5,7},如果从5开始,那么1,7可以同时加入队列,因为只要在这辆公交车内不管走多少遍,都是1辆公交车。题目需求求解的也是最少公交车数量,不是站点数量。* @param routes* @param S* @param T* @return*/public int numBusesToDestination(int[][] routes, int S, int T) {if(S==T) return 0;Map<Integer,List<Integer>> map = new HashMap<Integer, List<Integer>>();for(int i=0;i<routes.length;i++){for(int j=0;j<routes[i].length;j++){List<Integer> busList = map.getOrDefault(routes[i][j],new ArrayList<>());busList.add(i);map.put(routes[i][j],busList);}}Queue<Integer> queue = new ArrayDeque<>();queue.offer(S);Set<Integer> seen = new HashSet<>();int level = 0;while(!queue.isEmpty()){int size = queue.size();level++;for(int i=0;i<size;i++){int stop = queue.poll();if(stop == T) return level;for(int bus : map.get(stop)){if(seen.contains(bus)) continue;seen.add(bus);for(int j=0;j<routes[bus].length;j++){queue.offer(routes[bus][j]);}}}}return -1;}
代码1
代码2