您好,登录后才能下订单哦!
# LeetCode - Medium中Reconstruct Itinerary的示例分析
## 目录
- [问题描述与背景](#问题描述与背景)
- [基础概念解析](#基础概念解析)
- [欧拉路径与哈密尔顿路径](#欧拉路径与哈密尔顿路径)
- [有向图与邻接表](#有向图与邻接表)
- [暴力解法与局限性](#暴力解法与局限性)
- [Hierholzer算法详解](#hierholzer算法详解)
- [算法核心思想](#算法核心思想)
- [递归实现步骤](#递归实现步骤)
- [迭代实现对比](#迭代实现对比)
- [代码实现与优化](#代码实现与优化)
- [Python版本解析](#python版本解析)
- [Java版本关键点](#java版本关键点)
- [时间复杂度分析](#时间复杂度分析)
- [示例推演与Debug过程](#示例推演与debug过程)
- [标准测试案例](#标准测试案例)
- [边界条件测试](#边界条件测试)
- [循环机票处理](#循环机票处理)
- [变种问题探讨](#变种问题探讨)
- [多解情况处理](#多解情况处理)
- [无效行程检测](#无效行程检测)
- [加权机票场景](#加权机票场景)
- [总结与学习要点](#总结与学习要点)
- [参考资料](#参考资料)
## 问题描述与背景
**题目编号**:332
**难度**:Medium
**通过率**:约42%
给定一组机票(出发地,目的地),重构行程形成有效路径。所有机票必须且只能使用一次,路径需满足:
1. 从"JFK"出发
2. 字典序最小的行程
3. 形成完整欧拉路径
示例输入:
```python
tickets = [["MUC","LHR"],["JFK","MUC"],["SFO","SJC"],["LHR","SFO"]]
示例输出:
["JFK","MUC","LHR","SFO","SJC"]
特性 | 欧拉路径 | 哈密尔顿路径 |
---|---|---|
定义 | 经过每条边恰好一次 | 经过每个顶点恰好一次 |
判定条件 | 有向图:入度=出度(起点终点除外) | NP完全问题 |
本问题关联 | 必须使用所有机票(边) | 不适用 |
构建邻接表的Python示例:
from collections import defaultdict
graph = defaultdict(list)
for src, dst in sorted(tickets): # 提前排序保证字典序
graph[src].append(dst)
全排列法: 1. 生成所有可能的机票排列 2. 检查是否构成有效路径 3. 选择字典序最小解
缺陷分析: - 时间复杂度:O(n!) - 空间复杂度:O(n) - 当n=100时,计算量达9.3e+157次操作
graph TD
A[选择起点JFK] --> B[深度优先遍历]
B --> C{是否无路可走?}
C -->|是| D[加入路径]
C -->|否| B
D --> E[反向构建路径]
Python关键代码:
def dfs(node):
while graph[node]:
dfs(graph[node].pop(0))
route.append(node)
Java栈实现:
LinkedList<String> stack = new LinkedList<>();
stack.push("JFK");
while (!stack.isEmpty()) {
while (!graph.get(stack.peek()).isEmpty()) {
stack.push(graph.get(stack.peek()).poll());
}
route.addFirst(stack.pop());
}
完整解法:
def findItinerary(tickets):
graph = defaultdict(list)
for src, dst in sorted(tickets):
graph[src].append(dst)
route = []
def dfs(node):
while graph[node]:
dfs(graph[node].pop(0))
route.append(node)
dfs("JFK")
return route[::-1]
优化技巧:
1. 使用PriorityQueue
自动排序
2. 链表头插法避免反转
3. 栈的线程安全选择
输入:
[["JFK","SFO"],["JFK","ATL"],["SFO","ATL"],["ATL","JFK"],["ATL","SFO"]]
执行过程: 1. JFK → ATL (选择字典序较小者) 2. ATL → JFK 3. JFK → SFO 4. SFO → ATL 5. ATL → SFO
输出:
["JFK","ATL","JFK","SFO","ATL","SFO"]
单程票情况:
输入:[["JFK","LAX"]]
输出:["JFK","LAX"]
循环机票:
输入:[["JFK","ABC"],["ABC","JFK"],["JFK","XYZ"]]
输出:["JFK","ABC","JFK","XYZ"]
当存在多个字典序最小解时,算法天然选择第一条找到的路径。如需全部解,需修改为:
results = []
def dfs(node, path):
if 没有剩余机票:
results.append(path)
return
for i, neighbor in enumerate(graph[node]):
dfs(neighbor, path+[neighbor])
graph[node].insert(i, neighbor) # 回溯
增加前置检查:
in_degree = defaultdict(int)
out_degree = defaultdict(int)
for src, dst in tickets:
out_degree[src] += 1
in_degree[dst] += 1
# 检查欧拉路径条件
start = "JFK"
end = [k for k in out_degree if out_degree[k]-in_degree[k]==1]
if len(end) > 1: return []
”`
注:实际扩展内容时需增加更多: - 详细数学证明 - 各语言完整代码 - 性能测试数据 - 可视化图表 - 历史背景延伸等
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。