Bootstrap

学习记录:js算法(一百一十七):重新安排行程

重新安排行程

给你一份航线列表 tickets ,其中 tickets[i] = [fromi, toi] 表示飞机出发和降落的机场地点。请你对该行程进行重新规划排序。
所有这些机票都属于一个从 JFK(肯尼迪国际机场)出发的先生,所以该行程必须从 JFK 开始。如果存在多种有效的行程,请你按字典排序返回最小的行程组合。
例如,行程 [“JFK”, “LGA”] 与 [“JFK”, “LGB”] 相比就更小,排序更靠前。
假定所有机票至少存在一种合理的行程。且所有的机票 必须都用一次 且 只能用一次。

图一:
在这里插入图片描述

图二:
在这里插入图片描述

示例 1:图一
输入:tickets = [["MUC","LHR"],["JFK","MUC"],["SFO","SJC"],["LHR","SFO"]]
输出:["JFK","MUC","LHR","SFO","SJC"]

示例 2:图二
输入:tickets = [["JFK","SFO"],["JFK","ATL"],["SFO","ATL"],["ATL","JFK"],["ATL","SFO"]]
输出:["JFK","ATL","JFK","SFO","ATL","SFO"]
解释:另一种有效的行程是 ["JFK","SFO","ATL","JFK","ATL","SFO"] ,但是它字典排序更大更靠后。

思路一

function findItinerary(tickets) {
    const flights = {};
    tickets.forEach(ticket => {
        if (!flights[ticket[0]]) {
            flights[ticket[0]] = [];
        }
        flights[ticket[0]].push(ticket[1]);
    });

    // 对每个机场的目的地进行排序,以确保字典序最小的路径
    Object.keys(flights).forEach(key => {
        flights[key].sort();
    });

    const itinerary = [];

    function dfs(airport) {
        while (flights[airport] && flights[airport].length > 0) {
            const next = flights[airport].shift();
            dfs(next);
        }
        itinerary.unshift(airport);
    }

    dfs("JFK");
    return itinerary;
}

讲解
因为这是一个图论中的欧拉路径问题。我们需要找到从“JFK”机场出发,遍历所有机票且不重复的路径。这实际上是一个深度优先搜索(DFS)的问题,需要构建一个图,并从“JFK”开始进行搜索,同时保持路径的字典序最小。

  1. 构建图:使用一个Map来存储从每个机场出发的所有航班,Map的key是机场名称,value是一个按照字典序排序的机场列表,表示从该机场可以飞往的所有机场。
  2. 深度优先搜索(DFS):从“JFK”开始,递归地进行DFS。在每次递归调用中,我们选择下一个机场,将其从可用的航班中移除,并将该机场添加到路径中。当没有更多的航班可选时,递归返回。
  3. 回溯:在DFS中,当回溯时,我们需要恢复之前的状态,即将选择的航班重新放回可用航班列表中。
  4. 构建结果:在DFS的过程中,不断构建结果路径。由于我们按照字典序排序,所以最先找到的路径将是字典序最小的路径。
;