1 题目
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.
2 尝试解
2.1 分析
给定一系列指定了出发地和目的地的机票,即若干节点之间的有向边,问在指定了起始点的情况下,如何无重复连续地遍历这些边,如果有多种方式,则取字母序最小的方式。
典型的回溯算法,先求出从起始点开始,所有能到达的节点,然后遍历这些节点,求出下一步所能到达的节点,重复此过程,如果最终机票用尽,则是一种可行的方式,如果机票没用尽,但是下一步已没有可以去的节点,则不是一种可行的方式,回退剪枝。找出所有的方法,然后排序。
但是题目中只要求字母序最小的,所以上述方法容易超时。实际上,在要求字母序最小的情况下,该问题缩小为一个深度优先的搜索算法,只需要在搜索前将当前节点Node所有可达节点列表按照字母序排序,那么第一个可行的方式既是字母序最小的可行方式。
2.2 代码
class Solution {
public:
void FindItinerary(map<string,vector<string>>&reachable, vector<string>&itinerary, string&temp, int ticket, int tickets_size){
string cur_node = temp.substr(temp.size()-3,3);
if(ticket == tickets_size) {
itinerary.push_back(temp);
return;
}
if(reachable[cur_node].size() == 0) return;
for(int i = 0; i < reachable[cur_node].size() && !itinerary.size();i++){
string node = reachable[cur_node][i];
temp += node;
vector<string>::iterator it;
it = reachable[cur_node].begin();
while(it != reachable[cur_node].end()){
if(*it == node){
reachable[cur_node].erase(it);
break;
}
it++;
}
FindItinerary(reachable,itinerary,temp,ticket+1,tickets_size);
temp = temp.substr(0,temp.size()-3);
reachable[cur_node].insert(reachable[cur_node].begin()+i,node);
}
}
vector<string> findItinerary(vector<vector<string>>& tickets) {
map<string,vector<string>> reachable;
for(auto ticket : tickets){
reachable[ticket[0]].push_back(ticket[1]);
}
map<string,vector<string>>::iterator it;
it = reachable.begin();
while(it != reachable.end()){
sort(it->second.begin(),it->second.end());
it++;
}
vector<string> itinerary;
string temp = "JFK";
FindItinerary(reachable,itinerary,temp,0,tickets.size());
sort(itinerary.begin(),itinerary.end());
vector<string> result;
for(int i = 0; i < itinerary[0].size()/3;i++){
result.push_back(itinerary[0].substr(3*i,3));
}
return result;
}
};
3 标准解
class Solution {
public:
vector<string> findItinerary(vector<pair<string, string>> tickets) {
for (auto ticket : tickets)
targets[ticket.first].insert(ticket.second);
visit("JFK");
return vector<string>(route.rbegin(), route.rend());
}
map<string, multiset<string>> targets;
vector<string> route;
void visit(string airport) {
while (targets[airport].size()) {
string next = *targets[airport].begin();
targets[airport].erase(targets[airport].begin());
visit(next);
}
route.push_back(airport);
}
};