区间合并
600 字
3 分钟
区间合并

区间合并
区间合并用来处理多个区间之间的重叠关系。
比如:
[1, 3] 和 [2, 4]这两个区间有交集,可以合并成:
[1, 4]1、问题描述
给出若干个区间,要求把所有有交集的区间合并,最后得到互不重叠的区间。
例如:
[1, 3] [2, 6] [8, 10] [9, 12]合并后:
[1, 6] [8, 12]2、核心思路
区间合并一般分两步:
1. 按左端点从小到大排序2. 从前往后维护当前正在合并的区间 [st, ed]排序后,只需要看当前区间和维护区间是否相交。
3、如何判断是否相交
假设当前维护区间是:
[st, ed]新来的区间是:
[l, r]如果:
ed < l说明两个区间完全分开,需要开启一个新区间。
否则说明有交集,可以合并:
ed = max(ed, r)4、C++ 模板
#include <bits/stdc++.h>using namespace std;
typedef pair<int, int> PII;
int n;vector<PII> segs;
void merge_segments(vector<PII>& segs) { vector<PII> res;
sort(segs.begin(), segs.end());
int st = -2e9; int ed = -2e9;
for (auto seg : segs) { int l = seg.first; int r = seg.second;
if (ed < l) { if (st != -2e9) res.push_back({st, ed}); st = l; ed = r; } else { ed = max(ed, r); } }
if (st != -2e9) res.push_back({st, ed});
segs = res;}
int main() { cin >> n;
for (int i = 0; i < n; i++) { int l, r; cin >> l >> r; segs.push_back({l, r}); }
merge_segments(segs);
cout << segs.size() << endl; return 0;}5、手推一遍
输入:
[1, 3] [2, 6] [8, 10] [9, 12]先排序,顺序不变。
处理 [1, 3]:
当前区间 = [1, 3]处理 [2, 6],因为 2 <= 3,有交集:
当前区间 = [1, 6]处理 [8, 10],因为 6 < 8,开启新区间:
保存 [1, 6]当前区间 = [8, 10]处理 [9, 12],有交集:
当前区间 = [8, 12]最后保存 [8, 12]。
6、容易写错的地方
(1)忘记先排序
不排序的话,无法保证只和当前维护区间比较就够了。
(2)最后一个区间忘记加入答案
循环结束后还要:
if (st != -2e9) res.push_back({st, ed});(3)相邻端点是否合并要看题意
当前模板中:
if (ed < l)表示 [1, 3] 和 [3, 5] 会合并。
如果题目认为端点相接不算重叠,就要改成:
if (ed <= l)总结
区间合并的关键词是:
按左端点排序 + 维护当前右端点只要能判断新区间是否和当前区间相交,代码就很直接。
文章分享
如果这篇文章对你有帮助,欢迎分享给更多人!














