用最小堆一次性归并k个有序set:先封装各非空set的迭代器对,再以元素值构建小顶堆,每次取最小值、去重后加入vector,推进对应迭代器并重新入堆,总时间复杂度O(N)。

要将多个已排序的 std::set 合并为一个不重复、仍有序的结果集合,且整体时间复杂度严格控制在 O(N)(N 为所有元素总数),不能依赖插入式合并(如反复 insert 会退化为 O(N log N)),必须绕过红黑树的动态平衡开销,直接利用各 set 的底层有序性做归并。
前提:提取各 set 的有序迭代器范围
std::set 本身是有序容器,其 begin() 到 end() 迭代器天然构成升序序列。但注意:不能直接用 std::merge 多次两两合并,那样会产生中间临时容器和重复遍历。必须一次性归并 k 个有序序列。
第一步:把每个 set 的 begin() 和 end() 封装成迭代器对,存入 vector;确保所有 set 非空,空 set 可跳过——【空 set 不提供任何有效迭代器,push 前必须判空】。
这一步操作起来很简单,直接用 range-based for 循环 + emplace_back 即可。
立即学习“C++免费学习笔记(深入)”;
构建最小堆驱动多路归并
核心思路是用 priority_queue 维护 k 个当前最小候选值,每次弹出全局最小,再推进对应序列的迭代器。需自定义比较器,按元素值升序排列,但优先队列默认大顶堆,所以比较逻辑要反着写。
方法一:使用 tuple 存储(值,所属 set 索引,当前迭代器)
定义 struct 或用 tuple> 实现小顶堆。
方法二:封装 iterator wrapper 类,重载 operator<,更类型安全,但代码略长;实战中 tuple 更快上手。
初始化堆:对每个非空 set,取 *it 插入堆,并保存 it++ 后的下一个位置;【若某 set 只含一个元素,push 后 it == end(),后续不能再递增】。
执行归并并写入目标容器
步骤一:创建目标容器 std::vector<int>(非 set),因为 vector 的 push_back 是 O(1) 均摊,而 set 插入是 O(log N)。
步骤二:当堆非空时,pop 顶部元素,记为 val;检查结果 vector 是否为空或末尾元素 ≠ val(去重);若满足,push_back(val)。
步骤三:取出该元素对应的迭代器,若未达其 set 的 end(),则递增后重新 push 入堆(新值 + 新迭代器 + 原索引)。
这一步循环执行,直到堆为空。每轮只处理一个元素,总循环次数恰好等于不同元素个数 ≤ N,所有迭代器总移动步数也是 N,因此整体为 O(N)。
最后,若业务强要求返回 set,可用 vector 构造:return {vec.begin(), vec.end()};但这一步是 O(M log M)(M 为去重后大小),不属于归并主流程。



















