今天,给大家讲一下区间合并算法。
区间合并:顾名思义,就是将所有存在交集的区间进行合并。这种算法在处理时间序列数据、任务调度等场景中非常有用。
区间合并算法的实现通常涉及对区间进行排序,然后遍历排序后的区间列表,通过合并有交集的区间来生成新的、不重叠的区间集合。
具体来说,区间合并算法的实现步骤包括:
1.按区间左端点排序。
2.扫描整个区间,把可能有交集的区间合并。一共有三种情况:
(1)第一种情况:原区间包含新区间,此时区间不更新。
(2)第二种情况:原区间和新区间相交,左端点不变,右端点延长。
(3)第三种情况:原区间和新区间无交集,将原区间放入答案中,把新区间作为当前原区间。
下面,我们来看一个例题:
题目:区间合并
给定 n 个区间 [li , ri],要求合并所有有交集的区间。
注意如果在端点处相交,也算有交集。
输出合并完成后的区间个数。
输入格式:
第一行包含整数 n。
接下来 n 行,每行包含两个整数 l 和 r。
输出格式:
共一行,包含一个整数,表示合并区间完成后的区间个数。
数据范围:
1 ≤ n ≤ 100000 ,
−1e9 ≤ li ≤ ri ≤ 1e9
输入样例:
5
1 2
2 4
5 6
7 8
7 9
输出样例:
3
具体代码如下:
//区间合并
#include<algorithm>
#include<iostream>
#include<vector>
using namespace std;
vector<pair<int, int>> intervals;
int merge(vector<pair<int, int>>& intervals)
{
sort(intervals.begin(), intervals.end());//排序的目的:将区间的左端点对齐。
int st = -2e9, ed = -2e9;
vector<pair<int, int>> res;
for (auto intval : intervals)
{
if (ed < intval.first)
{
if (st != -2e9)res.push_back({ st,ed });
st = intval.first, ed = intval.second;
}
else
{
ed = max(ed, intval.second);//区间融合
}
}
if (st != -2e9) res.push_back({ st,ed });//将最后一个区间补上
return res.size();
}
int main()
{
int n;
scanf("%d", &n);
for (int i = 0; i < n; i++)
{
int l, r;
scanf("%d %d", &l, &r);
intervals.push_back({ l,r });
}
cout << merge(intervals);
}