青训营笔记7 | 豆包MarsCode AI刷题

102 阅读4分钟

问题描述

阿D的最佳飞行路线

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

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

求最小起飞次数。

测试样例

样例1:

输入:airports = [10, 12, 13, 12, 14]
输出:3

样例2:

输入:airports = [10, 11, 12, 13, 14]
输出:4

样例3:

输入:airports = [7, 7, 7, 8, 9, 7]
输出:1

解题思路

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

数据结构选择

  由于我们需要找到最短路径,可以考虑使用广度优先搜索(BFS)算法。BFS 非常适合解决这类问题,因为它会优先探索距离起点最近的节点,从而找到最短路径。

算法步骤

  1. 初始化

    • 使用一个队列来存储当前机场的索引和当前的起飞次数;
    • 使用一个集合来记录已经访问过的机场,避免重复访问。
  2. BFS 遍历

    • 从队列中取出当前机场的索引和起飞次数;
    • 如果当前机场是终点机场,返回当前的起飞次数;
    • 否则,将当前机场的相邻机场(i-1i+1)和同一家航空公司的其他机场加入队列,并标记为已访问。
  3. 终止条件

    • 当队列为空时,表示所有可能的路径都已探索完毕,但没有找到终点机场,返回一个错误值(如-1)。

实现及分析

def solution(airports):
    from collections import deque
    
    n = len(airports)
    queue = deque([(0, 0)])  # (当前机场索引, 起飞次数)
    visited = set([0])  # 记录已访问的机场
    
    while queue:
        current_index, steps = queue.popleft()
        
        # 如果当前机场是终点机场
        if current_index == n - 1:
            return steps
        
        # 探索相邻机场
        for neighbor in [current_index - 1, current_index + 1]:
            if 0 <= neighbor < n and neighbor not in visited:
                visited.add(neighbor)
                queue.append((neighbor, steps + 1))
        
        # 探索同一家航空公司的其他机场
        for i in range(n):
            if airports[i] == airports[current_index] 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. 初始化

    • 初始化队列和集合的时间复杂度为 O(1)O(1)
  2. BFS 遍历

    • 在最坏情况下,每个机场都会被访问一次。假设机场数量为 n,则 BFS 遍历的时间复杂度为 O(n)O(n)
    • 对于每个机场,需要检查其相邻机场和同一家航空公司的其他机场。检查相邻机场的时间复杂度为 O(1),检查同一家航空公司的其他机场的时间复杂度为 O(n)O(n)
    • 因此,BFS 遍历的总时间复杂度为 O(n2)O(n^2)

空间复杂度

  1. 队列

    • 在最坏情况下,队列中可能会存储所有机场的索引。假设机场数量为 n,则队列的空间复杂度为 O(n)O(n)
  2. 集合

    • 集合用于记录已访问的机场,最坏情况下会存储所有机场的索引。假设机场数量为 n,则集合的空间复杂度为 O(n)O(n)

优化

  当前的时间复杂度为 O(n2)O(n^2),主要是因为每次检查同一家航空公司的其他机场时需要遍历整个数组。可以考虑使用哈希表来优化这一部分,将同一家航空公司的机场索引存储在哈希表中,从而将检查同一家航空公司的其他机场的时间复杂度降低到 O(1)O(1)

def solution(airports):
    from collections import deque, defaultdict
    
    n = len(airports)
    queue = deque([(0, 0)])  # (当前机场索引, 起飞次数)
    visited = set([0])  # 记录已访问的机场
    
    # 使用哈希表存储同一家航空公司的机场索引
    airline_map = defaultdict(list)
    for i, airline in enumerate(airports):
        airline_map[airline].append(i)
    
    while queue:
        current_index, steps = queue.popleft()
        
        # 如果当前机场是终点机场
        if current_index == n - 1:
            return steps
        
        # 探索相邻机场
        for neighbor in [current_index - 1, current_index + 1]:
            if 0 <= neighbor < n and neighbor not in visited:
                visited.add(neighbor)
                queue.append((neighbor, steps + 1))
        
        # 探索同一家航空公司的其他机场
        for i in airline_map[airports[current_index]]:
            if i not in visited:
                visited.add(i)
                queue.append((i, steps + 1))
    
    return -1  # 如果没有找到路径,返回-1
  • 时间复杂度O(n)O(n)
  • 空间复杂度O(n)O(n)