Coding | [代码随想录][回溯] 332.重新安排行程

题面

给你一份航线列表 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考核做好准备,我必须考虑这是不是我此生仅有的机会。我尽量每天上传我的计划和完成情况,望大家监督。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值