原文链接:https://leetcode-cn.com/problems/reconstruct-itinerary/solution/332-zhong-xin-an-pai-xing-cheng-hui-su-fa-shen-sou/
题目描述:
给你一份航线列表
tickets
,其中tickets[i] = [fromi, toi]
表示飞机出发和降落的机场地点。请你对该行程进行重新规划排序。所有这些机票都属于一个从
JFK
(肯尼迪国际机场)出发的先生,所以该行程必须从JFK
开始。如果存在多种有效的行程,请你按字典排序返回最小的行程组合。
- 例如,行程
["JFK", "LGA"]
与["JFK", "LGB"]
相比就更小,排序更靠前。假定所有机票至少存在一种合理的行程。且所有的机票 必须都用一次 且 只能用一次。
输入:tickets = [["MUC","LHR"],["JFK","MUC"],["SFO","SJC"],["LHR","SFO"]]
输出:["JFK","MUC","LHR","SFO","SJC"]
输入:tickets = [["JFK","SFO"],["JFK","ATL"],["SFO","ATL"],["ATL","JFK"],["ATL","SFO"]]
输出:["JFK","ATL","JFK","SFO","ATL","SFO"]
解释:另一种有效的行程是 ["JFK","SFO","ATL","JFK","ATL","SFO"] ,但是它字典排序更大更靠后。
算法思路:
代码随想录:一个非常好的学数据结构和算法的微信公众号
递归模板:
backtracking() {
if (终止条件) {
存放结果;
}for (枚举同一个位置的所有可能性,可以想成节点孩子的数量) {
递归,处理节点;
backtracking();
回溯,撤销处理结果
}
}
- 首先如何存储图的结构,选择unordered_map<string,map<string,int>>进行存储,因为需要返回字典序最小的路径,因此后方选择map进行存储《开始城市,《到达城市,航班数》》这里利用航班数的自加和自减,进行城市之间是否连通。
- 其他详细内容见代码注释。
代码实现:
class Solution {
private:
unordered_map<string,map<string,int>> target;
//使用unordered_map存储图的结构,因为路线中可能存在环路,所以进行递归时,要及时对城市进行处理,又因为结果要按照字典序排序,返回最小字典序的答案,因此选择map实现。《出发城市,<到达城市,航班数>》,这里使用航班数来进行伪装的删除和添加操作。
bool track(int ticketsNum,vector<string>& result){
//递归的结束条件是什么呢?行程里的元素个数=票数+1,这个就是递归结束的条件
if(result.size()==ticketsNum+1){
return true;
}
//遍历存储好的图的结构:
//target[result[result.size()-1]],result中存的是string,target的类型是unordered_map<string,map<string,int>>,result的类型是vector<string>,则vec的类型为map<string,int>类型
//result[result.size()-1]在最初的状态时result中只有JFK,则result[1-1]为JFK,遍历与JFK相连的城市
for(auto &vec:target[result[result.size()-1]]){
if(vec.second>0){//如果航班数大于0,说明存在机票,
result.push_back(vec.first);//将到达的城市push到result
vec.second--;//航班数-1
if(track(ticketsNum,result)){//递归
return true;
}
result.pop_back();//回溯恢复原来的状态,将压入的值pop出,航班数+1
vec.second++;
}
}
return false;//没有返回true的情况下,返回false
}
public:
vector<string> findItinerary(vector<vector<string>>& tickets) {
vector<string> result;//存放最终的路线
for(auto& vec:tickets){//记录映射关系
target[vec[0]][vec[1]]++;// target[vec[0]]此时指的为《string,int》,后面跟[vec[1]]指向int航班数,++,表示存在航班数,记录映射关系,可以将其看做n维数组。
}
result.push_back("JFK");//将开始城市压入result中
track(tickets.size(),result);//递归
return result;
}
};