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

38 阅读4分钟

问题描述

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

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

求最小起飞次数。结果需要对 109+7109+7 取模(虽然在这个问题中没有提到取模,但处理大数时可以考虑)。

思路分析

  1. 问题本质

    • 这是一个典型的图的最短路径问题,可以使用广度优先搜索(BFS)来解决。
    • 每个机场可以看作图中的一个节点,相邻机场或同属一家航空公司的机场之间有边连接。
  2. 解决方案

    • 使用队列(Queue)来进行广度优先搜索。
    • 使用集合(Set)来记录已经访问过的机场,避免重复访问。
    • 初始状态为起点机场,起飞次数为0。
    • 在每一步中,探索当前机场的相邻机场和同属一家航空公司的机场,并将这些机场及其起飞次数加入队列。
    • 当到达终点机场时,返回起飞次数。

代码详解


import java.util.HashSet;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Set;

public class Main {
    public static int solution(int[] airports) {
        Queue<int[]> queue = new LinkedList<>();
        Set<Integer> visited = new HashSet<>();
        
        // 初始状态:起点机场,起飞次数为0
        queue.offer(new int[]{0, 0});
        visited.add(0);
        
        while (!queue.isEmpty()) {
            int[] current = queue.poll();
            int currentAirport = current[0];
            int currentFlights = current[1];
            
            // 如果到达终点,返回起飞次数
            if (currentAirport == airports.length - 1) {
                return currentFlights;
            }
            
            // 探索相邻机场
            if (currentAirport + 1 < airports.length && !visited.contains(currentAirport + 1)) {
                queue.offer(new int[]{currentAirport + 1, currentFlights + 1});
                visited.add(currentAirport + 1);
            }
            if (currentAirport - 1 >= 0 && !visited.contains(currentAirport - 1)) {
                queue.offer(new int[]{currentAirport - 1, currentFlights + 1});
                visited.add(currentAirport - 1);
            }
            
            // 探索相同航空公司的机场
            for (int i = 0; i < airports.length; i++) {
                if (airports[i] == airports[currentAirport] && i != currentAirport && !visited.contains(i)) {
                    queue.offer(new int[]{i, currentFlights + 1});
                    visited.add(i);
                }
            }
        }
        
        // 如果没有找到路径,返回-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
        System.out.println(solution(airports1) == 3); // 输出 true
        System.out.println(solution(airports2) == 4); // 输出 true
    }
}

知识总结

  1. 广度优先搜索(BFS)

    • BFS 是一种图的遍历算法,适用于寻找最短路径问题。通过队列来存储待处理的节点,确保每一步都按层次访问节点。
    • 使用集合记录已访问节点,避免重复处理,提高效率。
  2. 队列和集合

    • 在 Java 中,LinkedList 是一个常用的队列实现,可以高效地进行插入和删除操作。
    • HashSet 用于存储不重复的元素,适合记录已访问的节点。
  3. 数组处理

    • 使用 for 循环遍历数组中的每一个元素,处理每张卡牌。
    • 通过 airports[i] 获取当前机场的航空公司编号。
  4. 边界条件

    • 考虑边界条件,确保数组索引不越界。例如,处理相邻机场时,需要检查 currentAirport + 1 < airports.length 和 currentAirport - 1 >= 0

个人理解与学习建议

  1. 问题简化

    • 这个问题的核心是找到从起点到终点的最短路径。通过广度优先搜索,可以有效地解决这个问题。
    • 熟悉图的遍历算法,特别是BFS,有助于解决类似问题。
  2. 代码可读性

    • 在编写代码时,尽量使用有意义的变量名,如 currentAirport 和 currentFlights,这样可以使代码更易读。
    • 添加注释,特别是对于复杂逻辑的部分,可以提高代码的可维护性。
  3. 性能考虑

    • BFS 算法的时间复杂度为 O(n)O(n),适用于中等规模的输入。
    • 使用队列和集合可以有效地管理待处理节点和已访问节点,提高算法效率。
  4. 学习建议

    • 理解广度优先搜索:BFS 是一种重要的图遍历算法,适用于寻找最短路径问题。通过这个题目,可以加深对BFS的理解。
    • 掌握队列和集合:熟练使用 LinkedList 和 HashSet,可以在很多问题中派上用场。
    • 编写测试用例:在编写代码时,先思考测试用例,确保代码的正确性和鲁棒性。添加一些边界情况的测试用例,如只有一个机场、起点和终点同属一家航空公司等。
    • 代码优化:在确保代码正确性的基础上,可以考虑优化代码的性能,例如使用并行流处理大数组。