合并两个已排序无重叠vector区间集合,本质是归并加合并相邻可接续区间;关键判断是新区间左端点是否≤结果末尾区间右端点,若是则合并,否则追加。

合并两个 std::vector<:pair int>></:pair> 区间集合(无重叠、已排序)
如果两个输入集合各自内部无重叠且按左端点升序排列(这是常见前提),合并本质是归并 + 合并相邻可接续区间。不需要先拼接再排序再扫描,那样效率低还容易出错。
关键判断逻辑:当前待合并区间能否与结果末尾区间合并?即 new_interval.first (允许相邻,如 <code>[1,3] 和 [4,6] 合并为 [1,6]);若要求严格不重叠且不相邻,则用 改为 <code>。
- 用两个指针遍历两集合,每次取左端点更小的区间加入临时结果
- 插入后立即检查是否能与
result.back()合并:若可以,更新result.back().second;否则直接push_back - 注意空集合边界:任一集合为空时,直接拷贝另一集合(但拷贝后仍需做一次合并检查,因为另一集合末尾可能和刚插入的区间连上)
手写合并函数时怎么处理区间端点闭合性?
标准做法默认区间为 [left, right] 闭区间。合并逻辑依赖端点比较方式,一旦混用开/闭语义,merge 结果会错。例如 [1,3] 和 (3,6] 实际不重叠也不相邻,但若都当闭区间算就会错误合并。
- 统一文档或注释声明:所有
std::pair<int int></int>表示[first, second] - 合并条件必须与语义一致:闭区间相邻允许合并 → 用
new_first - 若底层数据来自不同系统(如某处用左闭右开),务必在进入合并前转换:如
[a,b)转为[a, b-1]再参与运算
为什么不能直接用 std::set_union?
std::set_union 是为有序容器设计的“集合并”,但它把区间当作离散元素,不会做几何意义上的区间合并。它只会把两个已排序的 vector 按字典序归并去重,输出仍是原始区间列表,完全不检测 [1,2] 和 [3,4] 是否应合成 [1,4]。
立即学习“C++免费学习笔记(深入)”;
- 它比较的是整个
pair,不是端点关系 - 输入即使满足无重叠,输出也必然保留所有原始区间,数量不变
- 真要用 STL 算法,得先用
std::merge归并两个 vector,再用单次扫描合并相邻可接区间 —— 这其实就是手动实现归并合并的两步拆解
性能与边界坑点:重复合并、整数溢出、空输入
实际代码里最容易漏掉的是空输入检查和溢出防护。比如合并 [INT_MAX-1, INT_MAX] 和 [INT_MAX, INT_MAX],计算 new_first 会溢出。
- 空输入:任一 vector 为空,不可跳过合并逻辑,因为另一方可能非空,且其内部需自合并(虽然题设说“无重叠”,但单集合内仍要保证最终结果最简)
- 溢出防护:改用
new_first - 1 替代 <code>last_second + 1,避免加法溢出 - 重复合并:不要对已合并好的结果反复调用同一合并函数,除非你明确需要幂等性 —— 通常不需要,且二次合并可能因浮点或精度问题意外拆分区间
合并区间的复杂点不在算法本身,而在于端点语义一致性与边界数值安全。哪怕输入“保证无重叠”,只要有一处用错比较符或忽略溢出,结果就不可信。


















