扫描线算法笔记(C++)
问题引入
给出飞机的起飞和降落时间的列表, 用序列 interval
表示. 请计算出天上同时最多有多少架飞机.
样例:
-
interval = [(1, 10), (2, 3), (5, 8), (4, 7)]
: 输出3
. 图解如下:
我们将线条的端点投射到x
轴上, 图中的虚线视为扫描线, 从左往右扫描, 每次扫描到一条线段起点, 就将飞机数加 1, 扫描到线段终点, 就将飞机数减 1. 去整个过程中的最大值即为答案.
代码实现
代码实现中需要注意以下几点:
- 要对时间段进行排序(按照起点排序), 否则无法保证事件按照时间顺序处理.
- 要记录端点是起飞还是降落, 否则无法正确处理.
- 事件保存的时候仅需保存时间点(起点/终点)以及标记(起飞/降落), 无需将时间段信息保存在事件中.
#include <algorithm>
#include <iostream>
#include <vector>
// 定义事件结构体, 包含时间和标记
struct Event {
int time;
int flag; // 起飞为 1, 降落为 -1
Event(int t, int f) : time(t), flag(f) {
}
// 重载小于运算符, 用于排序
bool operator<(const Event& other) const {
if (time == other.time) {
return flag < other.flag; // 降落事件优先处理
}
return time < other.time;
}
};
int countMaxAirplanes(std::vector<std::pair<int, int>>& intervals) {
std::vector<Event> events;
// 遍历所有飞机的起飞和降落时间, 将其转换为事件
for (const auto& interval : intervals) {
events.emplace_back(interval.first, 1); // 起飞事件
events.emplace_back(interval.second, -1); // 降落事件
}
// 对事件按时间排序
std::sort(events.begin(</