阿D的最佳飞行路线探索 | 豆包MarsCode AI刷题

113 阅读6分钟

问题描述

小C和他的领导小F计划一次飞行,但由于严格的航空管制,他们的飞机仅能按特定的路线飞行:飞机只能飞往当前机场的相邻机场或相同航空公司管理的机场。为了减少起飞次数,小C需要制定最优的飞行路线。机场由一个数组airports标识,其中:

  • 数组每个元素代表一个独特的机场,元素的值代表不同的航空公司。
  • airports[0]为起点,airports[airports.length - 1]为终点。
  • 假设小C当前在机场i,那么i - 1i + 1(如果存在)代表邻近机场,飞机可以直接前往。
  • 如果在机场i,且存在airports[i] == airports[j],则机场i和机场j同属一家航空公司,可直接飞往。

求最小起飞次数。

问题理解

需要找到从起点机场到终点机场的最小起飞次数。飞机可以飞往相邻的机场(即索引为i-1i+1的机场),或者飞往同一家航空公司的其他机场。

数据结构选择

  1. 队列(Queue) :用于BFS(广度优先搜索),确保按层级遍历机场。
  2. 集合(Set) :用于记录已经访问过的机场,避免重复访问。
  3. 字典(Dictionary) :用于存储每个航空公司的机场索引列表,加快查找同一家航空公司的机场。

解法一:使用集合

python代码
from collections import deque

def solution(airports):
    # 初始化队列和访问集合
    queue = deque([(0, 0)])  # (当前机场索引, 起飞次数)
    visited = set([0])  # 记录已经访问过的机场
    
    while queue:
        current_index, steps = queue.popleft()
        
        # 如果当前机场是终点,返回起飞次数
        if current_index == len(airports) - 1:
            return steps
        
        # 获取当前机场的航空公司
        current_airline = airports[current_index]
        
        # 检查相邻机场
        for neighbor in [current_index - 1, current_index + 1]:
            if 0 <= neighbor < len(airports) and neighbor not in visited:
                visited.add(neighbor)
                queue.append((neighbor, steps + 1))
        
        # 检查同一家航空公司的机场
        for i in range(len(airports)):
            if airports[i] == current_airline and i not in visited:
                visited.add(i)
                queue.append((i, steps + 1))
    
    return -1  # 如果没有找到路径,返回-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 )

可以进行哪些优化?

  1. 优化访问集合的使用

    • 当前代码中,每次检查相邻机场和同一家航空公司的机场时,都会将机场索引添加到visited集合中。这可能会导致重复添加,影响性能。
    • 可以考虑在将机场索引添加到队列时,再将其添加到visited集合中,以避免重复添加。
  2. 减少不必要的循环

    • 当前代码中,每次都会遍历整个airports数组来查找同一家航空公司的机场。这会导致不必要的循环。
    • 可以考虑使用字典来存储每个航空公司的机场索引列表,这样在查找同一家航空公司的机场时,可以直接从字典中获取,减少循环次数。
  3. 边界条件处理

    • 当前代码中,已经处理了边界条件(如neighbor的索引范围),但可以进一步优化,确保在处理边界条件时不会出现意外的错误。

解法二:BFS遍历

算法步骤

  1. 初始化

    • 创建一个队列,并将起点机场(索引为0)和起飞次数(初始为0)放入队列。
    • 创建一个集合,用于记录已经访问过的机场,并将起点机场加入集合。
    • 创建一个字典,用于存储每个航空公司的机场索引列表。
  2. BFS遍历

    • 从队列中取出当前机场索引和当前起飞次数。
    • 如果当前机场是终点机场,返回当前起飞次数。
    • 检查当前机场的相邻机场(i-1i+1),如果相邻机场未被访问过,将其加入队列和访问集合。
    • 检查同一家航空公司的其他机场,如果这些机场未被访问过,将其加入队列和访问集合。
  3. 返回结果

    • 如果队列为空且未找到终点机场,返回-1表示无法到达终点。

python代码实现

from collections import deque, defaultdict

def solution(airports):
    # 初始化队列和访问集合
    queue = deque([(0, 0)])  # (当前机场索引, 起飞次数)
    visited = set([0])  # 记录已经访问过的机场
    
    # 使用字典存储每个航空公司的机场索引列表
    airline_dict = defaultdict(list)
    for i, airline in enumerate(airports):
        airline_dict[airline].append(i)
    
    while queue:
        current_index, steps = queue.popleft()
        
        # 如果当前机场是终点,返回起飞次数
        if current_index == len(airports) - 1:
            return steps
        
        # 获取当前机场的航空公司
        current_airline = airports[current_index]
        
        # 检查相邻机场
        for neighbor in [current_index - 1, current_index + 1]:
            if 0 <= neighbor < len(airports) and neighbor not in visited:
                visited.add(neighbor)
                queue.append((neighbor, steps + 1))
        
        # 检查同一家航空公司的机场
        for i in airline_dict[current_airline]:
            if i not in visited:
                visited.add(i)
                queue.append((i, steps + 1))
    
    return -1  # 如果没有找到路径,返回-1

代码解释

  1. 字典的使用:通过使用defaultdict来存储每个航空公司的机场索引列表,可以减少在查找同一家航空公司的机场时的循环次数。
  2. 访问集合的优化:在将机场索引添加到队列时,再将其添加到visited集合中,避免重复添加。
  3. 减少不必要的条件检查:在检查相邻机场时,提前判断是否已经到达终点,从而减少不必要的条件检查。

复杂度分析

时间复杂度

  1. 初始化部分

    • 初始化队列和访问集合:O(1)
    • 构建航空公司字典:O(n),其中n是机场的数量。
  2. BFS遍历部分

    • 每个机场最多被访问一次,因此BFS遍历的时间复杂度是O(n)。
    • 对于每个机场,我们需要检查其相邻机场和同一家航空公司的机场。相邻机场最多有2个,同一家航空公司的机场最多有n个(极端情况下所有机场都属于同一家航空公司)。
    • 因此,每次检查的时间复杂度是O(n)。

综合来看,BFS遍历的总时间复杂度是O(n^2)。

空间复杂度

  1. 队列

    • 在最坏情况下,队列中最多存储n个机场索引,因此空间复杂度是O(n)。
  2. 访问集合

    • 访问集合中最多存储n个机场索引,因此空间复杂度是O(n)。
  3. 航空公司字典

    • 航空公司字典中最多存储n个机场索引,因此空间复杂度是O(n)。

综合来看,总的空间复杂度是O(n)。

总结

通过使用BFS算法,结合字典和集合来优化查找和避免重复访问,可以有效地找到从起点机场到终点机场的最小起飞次数。