问题背景
给定一个机场列表 airports,其中每个元素表示一个机场所属的航空公司编号。你需要从第一个机场出发,到达最后一个机场。每次起飞可以选择以下两种方式之一:
- 飞往相邻的机场(即前一个或后一个机场)。
- 飞往同一航空公司的其他机场。
目标是找出从第一个机场到最后一个机场所需的最小起飞次数。
解决思路
这是一个典型的最短路径问题,可以通过广度优先搜索(BFS)来解决。BFS适用于寻找无权图中的最短路径问题,因为它会逐层扩展节点,确保最先到达终点的路径是最短的。
具体步骤
-
初始化:
- 使用一个队列来存储待处理的机场位置。
- 使用一个集合来记录已经访问过的机场,避免重复访问。
- 使用一个字典来存储每个航空公司管理的所有机场的索引,以便快速查找。
-
构建航空公司索引字典:
- 遍历
airports列表,将每个机场的索引添加到对应的航空公司字典中。
- 遍历
-
开始 BFS:
- 将起点机场(索引 0)加入队列,并标记为已访问。
- 初始化起飞次数
takeoffs为 0。
-
处理队列中的每个机场:
- 对于队列中的每个机场,尝试所有可能的下一步:
- 检查相邻的机场(前一个和后一个机场)。
- 检查同一航空公司的其他机场。
- 如果找到终点机场(索引
len(airports) - 1),返回当前的起飞次数。 - 如果没有找到终点机场,将所有未访问过的下一站机场加入队列并标记为已访问。
- 对于队列中的每个机场,尝试所有可能的下一步:
-
增加起飞次数:
- 每次处理完当前层的所有机场后,增加起飞次数。
-
结束条件:
- 如果队列为空且未找到终点机场,理论上不会发生,因为题目保证有解。
Python 实现
以下是详细的 Python 实现代码:
from collections import deque, defaultdict
def solution(airports):
if len(airports) <= 1:
return 0
# 创建一个字典来存储每个航空公司管理的所有机场索引
airline_dict = defaultdict(list)
for index, airline in enumerate(airports):
airline_dict[airline].append(index)
# 初始化队列和访问集合
queue = deque([0])
visited = set([0])
takeoffs = 0
while queue:
# 遍历当前层的所有机场
for _ in range(len(queue)):
current_airport = queue.popleft()
# 如果到达了最后一个机场,则返回起飞次数
if current_airport == len(airports) - 1:
return takeoffs
# 获取当前机场的所有可能下一个机场
next_airports = []
# 添加相邻机场
if current_airport - 1 >= 0 and current_airport - 1 not in visited:
next_airports.append(current_airport - 1)
if current_airport + 1 < len(airports) and current_airport + 1 not in visited:
next_airports.append(current_airport + 1)
# 添加相同航空公司的其他机场
for airport_index in airline_dict[airports[current_airport]]:
if airport_index != current_airport and airport_index not in visited:
next_airports.append(airport_index)
# 将所有未访问过的下一站加入队列并标记为已访问
for airport in next_airports:
visited.add(airport)
queue.append(airport)
# 完成一层遍历后,增加起飞次数
takeoffs += 1
# 如果没有找到路径到达终点,理论上不会发生,因为题目保证有解
return -1
if __name__ == "__main__":
# You can add more test cases here
print(solution([10,12,13,12,14]) == 3 )
print(solution([10,11,12,13,14]) == 4 )
解释
-
初始化:
airline_dict存储每个航空公司管理的所有机场索引。queue存储待处理的机场索引,初始包含起点机场。visited记录已访问的机场索引,防止重复访问。takeoffs记录起飞次数,初始为 0。
-
BFS 过程:
- 每次从队列中取出一个机场,检查是否到达终点。
- 如果未到达终点,获取所有可能的下一站机场(相邻机场和同一航空公司的其他机场)。
- 将未访问过的下一站机场加入队列并标记为已访问。
- 每处理完一层机场后,增加起飞次数。
-
返回结果:
- 当找到终点机场时,返回当前的起飞次数。
- 如果队列为空且未找到终点机场,返回 -1(理论上不会发生)。