题面
给你一份航线列表 tickets ,其中 tickets[i] = [fromi, toi] 表示飞机出发和降落的机场地点。请你对该行程进行重新规划排序。
所有这些机票都属于一个从 JFK(肯尼迪国际机场)出发的先生,所以该行程必须从 JFK 开始。如果存在多种有效的行程,请你按字典排序返回最小的行程组合。
- 例如,行程
["JFK", "LGA"]与["JFK", "LGB"]相比就更小,排序更靠前。
假定所有机票至少存在一种合理的行程。且所有的机票 必须都用一次 且 只能用一次。
输入:tickets = [["JFK","SFO"],["JFK","ATL"],["SFO","ATL"],["ATL","JFK"],["ATL","SFO"]] 输出:["JFK","ATL","JFK","SFO","ATL","SFO"] 解释:另一种有效的行程是 ["JFK","SFO","ATL","JFK","ATL","SFO"] ,但是它字典排序更大更靠后。
思路
初次面对这道题的处子思路已经遗忘掉了,但是有一个反反复复嚼来嚼去最后也没解决的令人厌烦的印象。第二次面对的时候会从容很多。写出了这样一个基本的代码,也能看出来很多问题,谨以此篇自省。
class Solution {
public:
map<string, map<string, int>> flights;
vector<string> path;
bool backtracking(vector<vector<string>>& tickets){
if(path.size() == tickets.size() + 1) return true;
else{
string start = path[path.size() - 1];
map<string, int> flight = flights[start];
for(pair<string, int> f: flight){
if(f.second == 1){
path.push_back(f.first);
f.second = 0;
if(backtracking(tickets)) return true;
f.second = 1;
path.pop_back();
}
else continue;
}
}
return false;
}
vector<string> findItinerary(vector<vector<string>>& tickets) {
path.push_back("JFK");
for(vector<string> ticket: tickets){
flights[ticket[0]][ticket[1]] = 1;
}
backtracking(tickets);
return path;
}
};
从思路可以看出来,我对上一次carl标答的参考尚存一些印象。用一个一对多的map建立起起点->终点的映射,一个一对一的映射建立起机票->判断是否使用过的映射。
在运行测试用例的时候,可以看出我对flights全局变量的修改并没有成功。
在对比答案和问了GPT之后,我将这类错误归咎于我自己的程序设计基础并不扎实。我想对我自己强调几点:
为什么要用外层map映射很容易理解,内层为什么也用map而不是pair?
内层map可以实现排序,答案只要求输出一个有效的、按照字典序排序的第一个行程组合即可。无需做到整棵树的遍历。
为什么对全局变量的修改无效?
作为一个cser,你理应对这样的操作很敏感:
map<string, int> flight = flights[start];
for(pair<string, int> f: flight){
这里的flight和f都只是拷贝了一份数据,并没有真正地引用到全局变量处。所以正确语法应是:
map<string, int>& flight = flights[start]; // ✅ 用引用,避免拷贝
for(auto& f : flight){ // ✅ 注意这里也要用引用,才能修改 f.second
或者是:
map<string, int>& flight = flights[start]; // ✅ 用引用,避免拷贝
for(pair<const string, int>& f : flight){ // ✅ 注意这里也要用引用,才能修改 f.second
怎么实现只找到一条有效路径就返回?
这里的小巧思还要涉及到backtracking地返回值:为bool类型。若是bool类型就能在backtracking一旦找到一条有效路径的时候层层返回到根结点,直接return。若是void类型,则无法在递归调用backtracking的时候做判断,也就没法层层返回,被迫遍历整棵树。
另外
这道题考察回溯倒是考察地比较基础,考察到更多的更像是一些cpp的语法细节。很值得你记住。
但是最后因为剪枝不够而没有通过测评,也是无语住了。
另外的另外,从2025/7/30我就开始了为期两周的自训,为八月中旬的VIPL考核做好准备,我必须考虑这是不是我此生仅有的机会。我尽量每天上传我的计划和完成情况,望大家监督。

被折叠的 条评论
为什么被折叠?



