Leetcode 815. Bus Routes
阿新 • • 發佈:2019-01-08
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
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 };