回溯 Leetcode 332 重新安排行程

重新安排行程

Leetcode 332

学习记录自代码随想录

给你一份航线列表 tickets ,其中 ticketsi = 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" ,但是它字典排序更大更靠后。

要点:1.回溯模板上修改一些判断条件;

2.需要开始对车票排序,之后排过序后只要找到一个方案就是所需的字母排序最小的方案;

3.检查重复的车票,有的车票会重复;

4.检查使用过的车票以及车票开头是否等于上次末尾;

方法一:

cpp 复制代码
class Solution {
private:
    // vector<string> path = {"JFK"};
    string start = "JFK";
    vector<vector<string>> result;

    void backtracking(vector<vector<string>>& tickets, vector<int> used, vector<string> path){
        if(path.size() == tickets.size() + 1){
            result.push_back(path);
            return;
        }

        // start = path.back();
        for(int i = 0; i < tickets.size(); i++){
            // 已经对车票开始排过序了,所以只要找到一个方案就是所需的字母排序最小的方案
            if(result.size() > 0) break;
            // 检查重复的车票,有的车票会重复
            if (i > 0 && !used[i - 1] && tickets[i][0] == tickets[i - 1][0] && tickets[i][1] == tickets[i - 1][1]) {
                continue;
            }
            // 检查使用过的车票以及车票开头是否等于上次末尾
            if(used[i] == 1 || tickets[i][0] != start){
                continue;
            }
            start = tickets[i][1];
            used[i] = 1;
            path.push_back(tickets[i][1]);
            backtracking(tickets, used, path);
            path.pop_back();
            start = path.back();
            used[i] = 0;
        }

    }
public:
    vector<string> findItinerary(vector<vector<string>>& tickets){
        // path.clear();

        sort(tickets.begin(), tickets.end());
        vector<string> path = {"JFK"};
        vector<int> used(tickets.size(), 0);
        backtracking(tickets, used, path);
        // sort(result.begin(), result.end());

        return result[0];
    }
};

方法二:使用map存储机票路径

cpp 复制代码
//使用map存储
class Solution{
private:
    // 出发机场,<到达机场,标记机场是否使用过>
    unordered_map<string, map<string, int>> targets;
    // 注意此处result需要引用,不然输入的result只是为形参,不改变原来的result
    bool backtracking(vector<string>& result, vector<vector<string>>& tickets){
        if(result.size() == tickets.size() + 1){
            return true;
        }

        // target需要引用以对应更改targets, const防止更改
        // for(auto& target : targets[result.back()]){
        for(pair<const string, int>& target : targets[result.back()]){
            if(target.second > 0){
                result.push_back(target.first);
                target.second--;
                if(backtracking(result, tickets)) return true;  // 这样一找到结果就能返回
                result.pop_back();  // 回溯
                target.second++;  // 回溯
            }
        }

        return false;
    }

public:
    vector<string> findItinerary(vector<vector<string>>& tickets){
        targets.clear();

        // 记录映射关系,map是有序的,存储结果自动会排序,1代表没去过,0代表去过
        for(const vector<string>& vec : tickets){
            targets[vec[0]][vec[1]]++;
        }
        vector<string> result;
        result.push_back("JFK");
        backtracking(result, tickets);

        return result;
    }
};
相关推荐
CCCCCCCCharlie6 分钟前
深入解析I/O底层:文件描述符与缓冲区真相
linux·开发语言·c++·算法
Cccp.12329 分钟前
【leetcode】(十三)大数据处理
数据结构·算法·leetcode
学逆向的30 分钟前
C 选择结构的执行效率分析
c语言·开发语言·算法·网络安全
wzdark44 分钟前
动态规划算法的状态转移矩阵可视化分析5
算法·矩阵·动态规划
Pniubi1 小时前
力扣70爬楼梯
数据结构·算法·leetcode
人工智能培训1 小时前
具身智能环境交互与学习范式原理
大数据·linux·人工智能·学习·算法·机器学习
救救孩子把1 小时前
AI面试八股文-12_11-多模态大模型面试题
人工智能·面试·职场和发展·多模态·clip·rag·llave
纪念 2292 小时前
C++算法(三)
开发语言·c++·算法
学不会pwn不改名2 小时前
时间复杂度与空间复杂度详解
算法
RD_daoyi2 小时前
外贸独立站从0到1:平台选择 + 建站流程 + 新手避坑
大数据·服务器·网络·人工智能·搜索引擎·职场和发展