LeetCode 332 重新安排行程

LeetCode 332 重新安排行程

1.题目描述

给你一份航线列表 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.题解

  1. 本题可以先用哈希表记录起止机场,其中键是起始机场,值是一个多重集合,表示对应的终止机场。因为一个人可能坐过重复的路,所以我们需要使用多重集合储存重复值。
  2. 整个图最多存在一个死胡同(出度和入度相差1),且这个死胡同一定是最后一个访问到的,否则无法完成一笔画。
  3. DFS的调用其实是一个拆边的过程(既每次递归调用删除一条边,所有子递归都返回后,再将当前节点加入结果集保证了结果集的逆序输出),一定是递归到这个死胡同(没有子递归可以调用)后递归函数开始返回。所以死胡同是第一个加入结果集的元素。
  4. 最后逆序输出即可

C++:

class Solution {
public:
    unordered_map<string, multiset<string>> g ; // multiset 按字母序排序
    vector<string> ans ;
    vector<string> findItinerary(vector<vector<string>>& tickets) {
        for (auto& e : tickets) g[e[0]].insert(e[1]) ;
        dfs("JFK") ; 
        reverse(ans.begin(), ans.end()) ;//递归后,须颠倒顺序
        return ans ;
    }

    void dfs(string u) {
        while( g[u].size()) {
            auto ver = *g[u].begin() ;
            g[u].erase(g[u].begin()) ; //DFS要删除路径, 避免死循环
            dfs(ver) ;
        }
        ans.push_back(u) ;
    }
};

Golang:

var d map[string][]string
var ans []string
func findItinerary(tickets [][]string) []string {
    d = map[string][]string {} 
    for _, v := range tickets {
        d[v[0]] = append(d[v[0]], v[1]) 
    }
    for _, v := range d {
        sort.Strings(v) // 按字母序排序
    }
    ans = []string{} 
    dfs("JFK")
    return ans 
}
func dfs(f string ){
    for len(d[f]) > 0 {
        v := d[f][0] 
        d[f] = d[f][1:]
        dfs(v)
    }
    ans = append([]string{f},ans... ) // 在ans前插入 f 
}

原题:重新安排行程

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

进击的波吉

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值