Given a list of airline tickets represented by pairs of departure and arrival airports [from, to], reconstruct the itinerary in order. All of the tickets belong to a man who departs from JFK. Thus, the itinerary must begin with JFK.
Note:
If there are multiple valid itineraries, you should return the itinerary that has the smallest lexical order when read as a single string. For example, the itinerary [“JFK”, “LGA”] has a smaller lexical order than [“JFK”, “LGB”].
All airports are represented by three capital letters (IATA code).
You may assume all tickets form at least one valid itinerary.
Example 1:
Input: [["MUC", "LHR"], ["JFK", "MUC"], ["SFO", "SJC"], ["LHR", "SFO"]]
Output: ["JFK", "MUC", "LHR", "SFO", "SJC"]
Example 2:
Input: [["JFK","SFO"],["JFK","ATL"],["SFO","ATL"],["ATL","JFK"],["ATL","SFO"]]
Output: ["JFK","ATL","JFK","SFO","ATL","SFO"]
Explanation: Another possible reconstruction is ["JFK","SFO","ATL","JFK","ATL","SFO"].
But it is larger in lexical order.
思路:
这道题是有向图的搜索问题,需要快速查找从一个机场能到达的终点,所以考虑用hash来建立对应,c++中的unordered_map。而每一个机场对应的终点1. 可以有很多,2. 可以重复,3. 优先考虑lexical order在前的机场,因此最适合的结构是multiset。建立hash之后就可以用dfs进行线路的搜索。
知识点:topological sort 和dfs有何不同?
https://www.geeksforgeeks.org/topological-sorting/
需要的数据结构有:
unordered_map<string, multiset<string>>
方法1:
思路:
这种解法用dfs,每次选则终点中排序第一的,删掉这张票,递归搜索。仅当始发地没有目的地时可以打印出始发地,并且依次放回,如果上一个始发地还有票,继续dfs,如果没有,打印,继续返回。
所以这种打印的方式相当于postorder traversal。
易错点:
- 这里helper function里unordered_map<string, multiset<\string>> & m中的 reference就异常重要了:因为在每一层递归中, 我们都会对这个hash进行修改,不断删除已经用过的ticket,必须使用reference。
class Solution {
public:
vector<string> findItinerary(vector<pair<string, string>> tickets) {
vector<string> result;
unordered_map<string, multiset<string>> m;
for (auto ticket: tickets){
m[ticket.first].insert(ticket.second);
}
dfs(m, "JFK", result);
return vector<string> (result.rbegin(), result.rend());
}
void dfs(unordered_map<string, multiset<string>> & m, string start, vector<string> & result){
while (m[start].size() != 0){
string end = *m[start].begin();
m[start].erase(m[start].find(end));
dfs(m, end, result);
}
result.push_back(start);
return;
}
};
方法2:
grandyang: http://www.cnblogs.com/grandyang/p/5183210.html
因为相当于图的postorder traversal,也可以用stack来实现。我们将一个vertex入栈,当且仅当它没有它能到达的子节点。