Leetcode 815. Bus Routes
Problem:
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
.
这道题看到最少数量的公交车就应该有使用BFS的预感,先来说说我最开始考虑的解法,首先用一个哈希表记录每一个站点stop经过的所有线路的公交车,公交车编号为routes的索引。然后用visited记录访问过的公交车编号。BFS肯定是要维护一个队列的,里面的元素pair第一个元素代表第first路公交,第二个元素代表该公交经过第second站。首先将所有包含S站的公交全部放入队列,表示只需要一量公交可以到达的所有站点,然后在循环中记录下队列长度,然后将所有未访问过的公交车可能到达的所有站点加入队列中,同时pop开始元素,直到找到T为止,理论上说这个解法的时间复杂度是没问题的,可能是由于测试用例的缘故时间稍慢。
1 class Solution { 2 public: 3 int numBusesToDestination(vector<vector<int>>& routes, int S, int T) { 4 if(S == T) return 0; 5 unordered_map<int,vector<int>> um; 6 for(int i = 0;i != routes.size();++i){ 7 for(int j = 0;j != routes[i].size();++j){ 8 um[routes[i][j]].push_back(i); 9 } 10 } 11 vector<int> visited(routes.size(),false); 12 queue<pair<int,int>> q; 13 for(int i = 0;i != um[S].size();++i){ 14 int busline = um[S][i]; 15 for(int j = 0;j != routes[busline].size();++j){ 16 q.push(make_pair(busline,routes[busline][j])); 17 if(routes[busline][j] == T) 18 return 1; 19 } 20 visited[busline] = true; 21 } 22 int result = 2; 23 while(!q.empty()){ 24 int m = q.size(); 25 for(int i = 0;i != m;++i){ 26 int busline = q.front().first; 27 int stop = q.front().second; 28 q.pop(); 29 for(int k = 0;k != um[stop].size();++k){ 30 if(visited[um[stop][k]]) continue; 31 for(int t = 0;t != routes[um[stop][k]].size();++t){ 32 q.push(make_pair(um[stop][k],routes[um[stop][k]][t])); 33 if(routes[um[stop][k]][t] == T) return result; 34 } 35 visited[um[stop][k]] = true; 36 } 37 } 38 result++; 39 } 40 return -1; 41 } 42 };
接下来讲另一种解法,大致思路类似,不同的是这回pair中第一个元素记录站点,第二个元素记录坐过的公交车数量,visited记录做过的站点,然后在队列中不断添加该公交车可以换乘到达的站点。注意为什么push的一定是可以换乘到达的站点,这是由于同一条线路上的其他站点必然已经添加过队列了(细细体会这个细节)。
Code:
1 class Solution { 2 public: 3 int numBusesToDestination(vector<vector<int>>& routes, int S, int T) { 4 if(S == T) return 0; 5 unordered_map<int,vector<int>> um; 6 for(int i = 0;i != routes.size();++i){ 7 for(int j = 0;j != routes[i].size();++j){ 8 um[routes[i][j]].push_back(i); 9 } 10 } 11 unordered_set<int> visited; 12 visited.insert(S); 13 queue<pair<int,int>> q; 14 q.push(make_pair(S,0)); 15 while(!q.empty()){ 16 int stop = q.front().first; 17 int transfer = q.front().second; 18 q.pop(); 19 for(int i = 0;i != um[stop].size();++i){ 20 for(int j = 0;j != routes[um[stop][i]].size();++j){ 21 if(T == routes[um[stop][i]][j]) return transfer+1; 22 if(visited.find(routes[um[stop][i]][j]) == visited.end()){ 23 visited.insert(routes[um[stop][i]][j]); 24 q.push(make_pair(routes[um[stop][i]][j],transfer+1)); 25 } 26 } 27 routes[um[stop][i]].clear(); 28 } 29 } 30 return -1; 31 } 32 };