问题描述
阿D驾驶一架飞机需要从出发点抵达目的地,但是由于特殊的航空管制,对飞机的飞行路线有严格要求:飞机只能飞向当前机场的前后相邻机场或者相同航空公司管理的机场。现在阿D的leader要求阿D设计最佳的飞行路线,使得起飞次数最少。为此,阿D将所有的机场用一个数组arr表示,其中:
- 数组中每个元素表示不同的机场,元素的值表示不同的航空公司。
arr[0]表示出发点,arr[arr.length - 1]表示目的地。- 假设当前在机场
i(数组下标为i),则i - 1(i - 1 >= 0)和i + 1(i + 1 < arr.length)表示当前机场的前后机场,则飞机可以飞向编号为i - 1和i + 1的机场。 - 假设当前在机场
i,且数组中存在arr[i] == arr[j],则表示机场i和机场j为相同航空公司管理,则飞机可以飞向编号为j的机场。
输入格式
用数组表示所有机场
数据范围:
1 <= arr.length <= 5 * 10^4-10^8 <= arr[i] <= 10^8
输出格式
最少起飞次数
示例 1:
输入:arr = [10,12,13,12,14]
输出:3
最佳飞行路线:机场编号 0(出发点) -> 机场编号 1 -> 机场编号 3 -> 机场编号 4(目的地)
说明:arr[1]和arr[3]等于 12,为相同航空公司管理,机场编号 1 可以直接飞到机场编号 3
示例 2:
输入:arr = [10,11,12,13,14]
输出:4
最佳飞行路线:机场编号 0(出发点) -> 机场编号 1 -> 机场编号 2 -> 机场编号 3 -> 机场编号 4(目的地)
说明:数组中均为不同机场,只能逐一向前飞行
思路:
-
建图:
- 当前机场的相邻机场为
i - 1和i + 1(如果存在)。 - 同一航空公司管理的机场构成直接连通的节点。
- 当前机场的相邻机场为
-
搜索策略:
使用 BFS,从起点开始逐层扩展,直到到达目的地。BFS 可以保证第一次到达终点时路径最短。 -
优化访问:
- 使用
visited数组记录是否访问过一个节点,防止重复访问。 - 记录每个航空公司所有机场的索引,当访问某个航空公司时,统一标记这些节点为访问过。
- 使用
代码展示
#include <iostream>
#include <queue>
#include <unordered_map>
#include <unordered_set>
#include <vector>
int solution(std::vector<int> airports) {
int n = airports.size();
if (n == 1)
return 0;
std::unordered_map<int, std::vector<int>> company_to_airports;
for (int i = 0; i < n; ++i) {
company_to_airports[airports[i]].push_back(i);
}
std::queue<int> q;
std::vector<bool> visited(n, false);
q.push(0);
visited[0] = true;
int steps = 0;
while (!q.empty()) {
int size = q.size();
for (int i = 0; i < size; ++i) {
int curr = q.front();
q.pop();
if (curr == n - 1)
return steps;
if (curr - 1 >= 0 && !visited[curr - 1]) {
q.push(curr - 1);
visited[curr - 1] = true;
}
if (curr + 1 < n && !visited[curr + 1]) {
q.push(curr + 1);
visited[curr + 1] = true;
}
if (company_to_airports.count(airports[curr])) {
for (int neighbor : company_to_airports[airports[curr]]) {
if (!visited[neighbor]) {
q.push(neighbor);
visited[neighbor] = true;
}
}
company_to_airports.erase(airports[curr]);
}
}
++steps;
}
return -1;
}
int main() {
// 测试用例
std::vector<int> airports1 = {10, 12, 13, 12, 14};
std::vector<int> airports2 = {10, 11, 12, 13, 14};
std::cout << (solution(airports1) == 3) << std::endl;
std::cout << (solution(airports2) == 4) << std::endl;
return 0;
}
代码分析
- 记录航空公司机场:用哈希表
company_to_airports,键是航空公司编号,值是所有机场索引的列表。 - BFS 搜索:从起点出发,依次访问相邻机场和同一航空公司管理的机场,直到到达终点。
- 访问优化:每访问过一个机场,就标记为已访问;访问完某个航空公司所有机场后,从哈希表中删除该航空公司,避免重复处理。