[LeetCode] 815. Bus Routes 公交路线
We have a list of bus routes. Each routes[i]
is a bus route that the i-th bus repeats forever. For example if routes[0] = [1, 5, 7]
, this means that the first bus (0-th indexed) travels in the sequence 1->5->7->1->5->7->1->... forever.
We start at bus stop S
(initially not on a bus), and we want to go to bus stop T
. Travelling by buses only, what is the least number of buses we must take to reach our destination? Return -1 if it is not possible.
Example: Input: routes = [[1, 2, 7], [3, 6, 7]] S = 1 T = 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.
Note:
1 <= routes.length <= 500
.1 <= routes[i].length <= 500
.0 <= routes[i][j] < 10 ^ 6
.
有一个表示公交路线的二维数组,每一行routes[i]代表一辆公交车循环运行的环形路线,求最少需要坐多少辆公交车才能从巴士站S到达T。
解法:BFS,先对原来的二维数组进行处理,二维数组的每一行代表这辆公交车能到达的站点,用HashMap记录某站点有哪个公交经过。这样处理完以后就知道每一个站点都有哪个公交车经过了。然后用一个queue记录当前站点,对于当前站点的所有经过的公交循环,每个公交又有自己的下一个站点。可以想象成一个图,每一个公交站点 被多少个公交经过,也就是意味着是个中转站,可以连通到另外一个公交上, 因为题目求的是经过公交的数量而不关心经过公交站点的数量,所以在BFS的时候以公交(也就是routes的下标)来扩展。
Java:
class Solution { public int numBusesToDestination(int[][] routes, int S, int T) { HashSet<Integer> visited = new HashSet<>(); Queue<Integer> q = new LinkedList<>(); HashMap<Integer, ArrayList<Integer>> map = new HashMap<>(); int ret = 0; if (S==T) return 0; for(int i = 0; i < routes.length; i++){ for(int j = 0; j < routes[i].length; j++){ ArrayList<Integer> buses = map.getOrDefault(routes[i][j], new ArrayList<>()); buses.add(i); map.put(routes[i][j], buses); } } q.offer(S); while (!q.isEmpty()) { int len = q.size(); ret++; for (int i = 0; i < len; i++) { int cur = q.poll(); ArrayList<Integer> buses = map.get(cur); for (int bus: buses) { if (visited.contains(bus)) continue; visited.add(bus); for (int j = 0; j < routes[bus].length; j++) { if (routes[bus][j] == T) return ret; q.offer(routes[bus][j]); } } } } return -1; } }
Java:
public int numBusesToDestination(int[][] routes, int S, int T) { HashMap<Integer, HashSet<Integer>> to_routes = new HashMap<>(); for (int i = 0; i < routes.length; ++i) for (int j : routes[i]) { if (!to_routes.containsKey(j)) to_routes.put(j, new HashSet<Integer>()); to_routes.get(j).add(i); } Queue<Point> bfs = new ArrayDeque(); bfs.offer(new Point(S, 0)); HashSet<Integer> seen = new HashSet<>(); seen.add(S); while (!bfs.isEmpty()) { int stop = bfs.peek().x, bus = bfs.peek().y; bfs.poll(); if (stop == T) return bus; for (int route_i : to_routes.get(stop)) for (int next_stop : routes[route_i]) if (!seen.contains(next_stop)) { seen.add(next_stop); bfs.offer(new Point(next_stop, bus + 1)); } } return -1; }
Python:
def numBusesToDestination(self, routes, S, T): to_routes = collections.defaultdict(set) for i,route in enumerate(routes): for j in route: to_routes[j].add(i) bfs = [(S,0)] seen = set([S]) for stop, bus in bfs: if stop == T: return bus for route_i in to_routes[stop]: for next_stop in routes[route_i]: if next_stop not in seen: bfs.append((next_stop, bus+1)) seen.add(next_stop) routes[route_i] = [] return -1
Python:
# Time: O(|V| + |E|) # Space: O(|V| + |E|) import collections class Solution(object): def numBusesToDestination(self, routes, S, T): """ :type routes: List[List[int]] :type S: int :type T: int :rtype: int """ if S == T: return 0 to_route = collections.defaultdict(set) for i, route in enumerate(routes): for stop in route: to_route[stop].add(i) result = 1 q = [S] lookup = set([S]) while q: next_q = [] for stop in q: for i in to_route[stop]: for next_stop in routes[i]: if next_stop in lookup: continue if next_stop == T: return result next_q.append(next_stop) to_route[next_stop].remove(i) lookup.add(next_stop) q = next_q result += 1 return -1
C++:
int numBusesToDestination(vector<vector<int>>& routes, int S, int T) { unordered_map<int, unordered_set<int>> to_route; for (int i = 0; i < routes.size(); ++i) for (auto& j : routes[i]) to_route[j].insert(i); queue<pair<int, int>> bfs; bfs.push(make_pair(S, 0)); unordered_set<int> seen = {S}; while (!bfs.empty()) { int stop = bfs.front().first, bus = bfs.front().second; bfs.pop(); if (stop == T) return bus; for (auto& route_i : to_route[stop]) { for (auto& next_stop : routes[route_i]) if (seen.find(next_stop) == seen.end()) { seen.insert(next_stop); bfs.push(make_pair(next_stop, bus + 1)); } routes[route_i].clear(); } } return -1; }
All LeetCode Questions List 题目汇总