思路分析
这个问题是一个典型的图搜索问题,可以使用广度优先搜索(BFS)来解决。我们需要找到从起点(airports[0])到终点(airports[airports.length - 1])的最短路径,其中路径的长度表示起飞次数。
- 图的表示:每个机场代表一个节点,如果两个机场可以直接飞行(相邻或相同航空公司),则它们之间存在一条边。
- 搜索策略:使用BFS进行搜索,因为BFS能够找到从起点到终点的最短路径(在无权图中)。
- 队列和访问集合:使用队列来存储待访问的节点,使用集合来记录已经访问过的节点,防止重复访问。
- 终止条件:当队列中的某个节点是终点时,搜索结束,返回当前的起飞次数。
图解
以样例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进行逐层扩展,通过检查相邻和相同航空公司机场来寻找最短路径。