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

130 阅读4分钟

思路分析

这个问题是一个典型的图搜索问题,可以使用广度优先搜索(BFS)来解决。我们需要找到从起点(airports[0])到终点(airports[airports.length - 1])的最短路径,其中路径的长度表示起飞次数。

  1. 图的表示:每个机场代表一个节点,如果两个机场可以直接飞行(相邻或相同航空公司),则它们之间存在一条边。
  2. 搜索策略:使用BFS进行搜索,因为BFS能够找到从起点到终点的最短路径(在无权图中)。
  3. 队列和访问集合:使用队列来存储待访问的节点,使用集合来记录已经访问过的节点,防止重复访问。
  4. 终止条件:当队列中的某个节点是终点时,搜索结束,返回当前的起飞次数。

图解

以样例1为例:

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

  • 起点是0(机场10),终点是4(机场14)。
  • 第一层:访问0(机场10),可以向1(机场12)和2(机场13)飞行(相邻),并且发现3(机场12,相同航空公司)也可以飞行。
  • 第二层:访问1(机场12),发现2(机场13,已访问)和4(机场14,目标)可以飞行。
  • 第三层:访问2(机场13),发现3(机场12,已访问)和4(机场14,目标)可以飞行。
  • 在第三层访问到终点4(机场14),因此最小起飞次数为3。

代码详解

import java.util.*;

public class Main {
    public static int solution(int[] airports) {
        // 初始化队列和访问集合
        Queue<Integer> queue = new LinkedList<>();
        Set<Integer> visited = new HashSet<>();
        
        // 将起点加入队列,并标记为已访问
        queue.offer(0);
        visited.add(0);
        
        // 初始化起飞次数
        int takeoffCount = 0;
        
        // BFS 主循环
        while (!queue.isEmpty()) {
            int size = queue.size();
            for (int i = 0; i < size; i++) {
                int current = queue.poll();
                
                // 如果当前机场是终点,返回起飞次数
                if (current == airports.length - 1) {
                    return takeoffCount;
                }
                
                // 检查相邻机场
                if (current - 1 >= 0 && !visited.contains(current - 1)) {
                    queue.offer(current - 1);
                    visited.add(current - 1);
                }
                if (current + 1 < airports.length && !visited.contains(current + 1)) {
                    queue.offer(current + 1);
                    visited.add(current + 1);
                }
                
                // 检查相同航空公司的机场
                for (int j = 0; j < airports.length; j++) {
                    if (airports[j] == airports[current] && j != current && !visited.contains(j)) {
                        queue.offer(j);
                        visited.add(j);
                    }
                }
            }
            // 每层遍历结束后,起飞次数加一
            takeoffCount++;
        }
        
        // 如果无法到达终点,返回 -1(理论上不可能,因为总能通过所有机场遍历一遍)
        return -1;
    }

    public static void main(String[] args) {
        int[] airports1 = {10, 12, 13, 12, 14};
        int[] airports2 = {10, 11, 12, 13, 14};

        System.out.println(solution(airports1) == 3); // true
        System.out.println(solution(airports2) == 4); // true
    }
}

关键点总结

  • 使用BFS来寻找最短路径。
  • 队列存储待访问的节点,集合记录已访问的节点。
  • 每层遍历结束时,起飞次数加一。
  • 通过相邻机场和相同航空公司机场两个条件来扩展搜索范围。

思路总结:

本题是关于寻找最佳飞行路线的问题,即找到从起点机场到终点机场的最短起飞次数。这可以看作是一个无权图的最短路径问题,因此采用广度优先搜索(BFS)策略是合适的。

在解决方案中,我们首先初始化一个队列来存储待访问的机场,并使用一个集合来记录已经访问过的机场,以避免重复访问。然后,我们将起点机场加入队列并标记为已访问。

接下来,我们进行BFS的主循环,直到队列为空。在每次循环中,我们遍历当前层的所有机场,并检查它们的相邻机场以及相同航空公司的机场。如果某个相邻或相同航空公司的机场尚未被访问,则将其加入队列并标记为已访问。

当我们访问到终点机场时,即找到了最短路径,此时返回起飞次数。如果队列为空时仍未找到终点,则理论上不可能(因为总能通过遍历所有机场到达终点),但代码中返回-1作为无法到达的标记。

整个解决方案的核心在于利用BFS进行逐层扩展,通过检查相邻和相同航空公司机场来寻找最短路径。