
本文介绍如何在python中高效合并两个各含2000万+元素、已排序且仅有少量差异的列表,避免o(n log n)排序开销,通过`heapq.merge`与`dict.fromkeys`实现近线性时间复杂度的去重合并。
当处理规模达千万级以上的有序列表时,常规的 sorted(set(list_1 + list_2)) 或 sorted(set(list_1) | set(list_2)) 方案会严重低效——根本原因在于:
✅ 你已拥有两个严格升序排列的输入列表;
❌ 却仍调用 sorted() 对总计约4000万个元素进行全量排序,时间复杂度为 O(N log N) ≈ O(4×10⁷ × log₂(4×10⁷)),实测耗时50分钟即源于此;
❌ 同时,set() 构造过程不仅丢失顺序,还需对全部元素哈希、判重、重新分配内存,进一步加剧开销。
真正高效的解法应尊重输入的有序性,采用归并(merge)思想:
✅ 推荐方案:heapq.merge + dict.fromkeys
import heapq # 假设 list_1 和 list_2 均为升序、元素可哈希(如 str/int) combined = list(dict.fromkeys(heapq.merge(list_1, list_2)))
- heapq.merge(list_1, list_2):以 O(N) 时间复杂度流式归并两个有序序列(类似归并排序中的“合并”步骤),输出一个惰性迭代器,不一次性加载全部数据到内存;
- dict.fromkeys(...):利用 Python 3.7+ 中 dict 保持插入顺序的特性,实现稳定去重(保留首次出现位置),时间复杂度 O(N),且比 set() + sorted() 更轻量;
- list(...):最终转为列表(若后续需随机访问)。
? 示例验证:list_1 = ['a', 'b', 'c', 'x'] list_2 = ['a', 'b', 'd', 'y'] combined = list(dict.fromkeys(heapq.merge(list_1, list_2))) # → ['a', 'b', 'c', 'd', 'x', 'y']
⚠️ 关键注意事项
- 输入必须严格有序:heapq.merge 不校验顺序,若输入乱序,结果将错误;
- 元素需可哈希:dict.fromkeys 要求键值可哈希(常见类型如 str, int, tuple 等均满足);
- 内存友好性:heapq.merge 返回迭代器,dict.fromkeys 逐个消费,整体内存占用远低于构造完整 set 或临时大列表;
- 无需额外安装依赖:纯标准库方案,零第三方依赖。
? 性能对比(估算)
| 方法 | 时间复杂度 | 实测典型耗时(2000万级) | 内存峰值 |
|---|---|---|---|
| sorted(set(list_1 + list_2)) | O(N log N) | ~50 分钟 | 极高(临时列表 + set) |
| heapq.merge + dict.fromkeys | O(N) | 低(流式处理 + 单次遍历) |
✅ 进阶建议(超大规模场景)
若列表过大导致单机内存仍紧张,可考虑:
- 使用生成器分块处理(如每次归并100万项后写入磁盘);
- 利用 itertools.islice 流式截取结果前N项(如只需Top-K);
- 对于不可哈希元素(如嵌套字典),改用 itertools.groupby 配合 sorted(..., key=...) 归并后去重(需自定义键函数)。
综上,善用输入的有序性是性能跃迁的关键。抛弃“先拼接、再去重、最后排序”的惯性思维,转向 merge → dedupe 的流式范式,即可将数十分钟任务压缩至秒级,同时显著降低资源消耗。










