332 Reconstruct Itinerary

178 篇文章 0 订阅
160 篇文章 0 订阅

1 题目

Given a list of airline tickets represented by pairs of departure and arrival airports [from, to], reconstruct the itinerary in order. All of the tickets belong to a man who departs from JFK. Thus, the itinerary must begin with JFK.

Note:

  1. If there are multiple valid itineraries, you should return the itinerary that has the smallest lexical order when read as a single string. For example, the itinerary ["JFK", "LGA"] has a smaller lexical order than ["JFK", "LGB"].
  2. All airports are represented by three capital letters (IATA code).
  3. You may assume all tickets form at least one valid itinerary.

Example 1:

Input: [["MUC", "LHR"], ["JFK", "MUC"], ["SFO", "SJC"], ["LHR", "SFO"]]
Output: ["JFK", "MUC", "LHR", "SFO", "SJC"]

Example 2:

Input: [["JFK","SFO"],["JFK","ATL"],["SFO","ATL"],["ATL","JFK"],["ATL","SFO"]]
Output: ["JFK","ATL","JFK","SFO","ATL","SFO"]
Explanation: Another possible reconstruction is ["JFK","SFO","ATL","JFK","ATL","SFO"].
             But it is larger in lexical order.

2 尝试解

2.1 分析

给定一系列指定了出发地和目的地的机票,即若干节点之间的有向边,问在指定了起始点的情况下,如何无重复连续地遍历这些边,如果有多种方式,则取字母序最小的方式。

典型的回溯算法,先求出从起始点开始,所有能到达的节点,然后遍历这些节点,求出下一步所能到达的节点,重复此过程,如果最终机票用尽,则是一种可行的方式,如果机票没用尽,但是下一步已没有可以去的节点,则不是一种可行的方式,回退剪枝。找出所有的方法,然后排序。

但是题目中只要求字母序最小的,所以上述方法容易超时。实际上,在要求字母序最小的情况下,该问题缩小为一个深度优先的搜索算法,只需要在搜索前将当前节点Node所有可达节点列表按照字母序排序,那么第一个可行的方式既是字母序最小的可行方式。

2.2 代码

class Solution {
public:
    void FindItinerary(map<string,vector<string>>&reachable, vector<string>&itinerary, string&temp, int ticket, int tickets_size){
        string cur_node = temp.substr(temp.size()-3,3);
        if(ticket == tickets_size) {
            itinerary.push_back(temp);
            return;
        }
        if(reachable[cur_node].size() == 0) return;
        for(int i = 0; i < reachable[cur_node].size() && !itinerary.size();i++){
            string node = reachable[cur_node][i];
            temp += node;
            vector<string>::iterator it;
            it = reachable[cur_node].begin();
            while(it != reachable[cur_node].end()){
                if(*it == node){
                    reachable[cur_node].erase(it);
                    break;
                }
                it++;
            }
            FindItinerary(reachable,itinerary,temp,ticket+1,tickets_size);
            temp = temp.substr(0,temp.size()-3);
            reachable[cur_node].insert(reachable[cur_node].begin()+i,node);
        }
    }
    vector<string> findItinerary(vector<vector<string>>& tickets) {
        map<string,vector<string>> reachable;
        for(auto ticket : tickets){
            reachable[ticket[0]].push_back(ticket[1]);
        }
        map<string,vector<string>>::iterator it;
        it = reachable.begin();
        while(it != reachable.end()){
            sort(it->second.begin(),it->second.end());
            it++;
        }
        vector<string> itinerary;
        string temp = "JFK";
        FindItinerary(reachable,itinerary,temp,0,tickets.size());
        sort(itinerary.begin(),itinerary.end());
        vector<string> result;
        for(int i = 0; i < itinerary[0].size()/3;i++){
            result.push_back(itinerary[0].substr(3*i,3));
        }
        return result;
    }
};

3 标准解

class Solution {
public:
    vector<string> findItinerary(vector<pair<string, string>> tickets) {
        for (auto ticket : tickets)
            targets[ticket.first].insert(ticket.second);
        visit("JFK");
        return vector<string>(route.rbegin(), route.rend());
    }

    map<string, multiset<string>> targets;
    vector<string> route;

    void visit(string airport) {
        while (targets[airport].size()) {
            string next = *targets[airport].begin();
            targets[airport].erase(targets[airport].begin());
            visit(next);
        }
        route.push_back(airport);
    }
};

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值