1. 程式人生 > >Leetcode 815. Bus Routes

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.

 

Solution:

  這道題看到最少數量的公交車就應該有使用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 };