如何以O(n)复杂度最快实现多个预排序数组合并为无重复有序数组
多预排序数组合并去重的高性能实现方案
核心思路
完全不需要把所有数组拼接后做全量排序——这个方案的时间复杂度是O(n logn),完全浪费了输入数组已经预排序的前置条件。基于k路归并的思路实现,可以把整体时间复杂度压到接近线性级别,天然支持去重,性能远高于全量排序方案。
具体逻辑非常简单:
- 给每个非空的输入数组维护一个读取位置指针,初始全部指向对应数组的第0个元素
- 每一轮从所有指针指向的元素里选出最小值,和上一次加入结果集的元素做比对:
- 如果和上一次入结果的值相等,直接跳过当前值,把对应指针后移
- 如果和上一次入结果的值不相等,把当前值加入结果集,再把对应指针后移
- 直到所有数组的指针都走到数组末尾,整个流程结束
不同场景的性能权衡
- 当输入的数组数量较少(比如k<100):直接线性遍历所有指针找最小值的方式性能最高。因为没有堆结构的额外内存开销,线性遍历的CPU缓存命中率极高,实际运行速度比带堆的实现快30%以上,整体的性能开销远低于全量排序
- 当输入的数组数量非常大(比如k>1000):可以用最小堆维护当前指针指向的元素值,每次直接取堆顶的最小值,把单轮找最小值的开销从O(k)降到O(logk),整体时间复杂度为O(n logk),比线性遍历找最小值的方式性能更优
可直接落地的代码实现
针对常规业务场景(数组数量不多)的最高性能实现:
function mergePreSortedArrays(arrays) { // 初始化指针列表,过滤空数组减少无效遍历 const pointerList = arrays .map(item => ({ data: item, currentIndex: 0 })) .filter(item => item.data.length > 0); const result = []; let lastAddedValue = undefined; while (pointerList.length > 0) { // 线性遍历找当前轮的最小值对应的指针位置 let minPointerPos = 0; for (let i = 1; i < pointerList.length; i++) { const currentVal = pointerList[i].data[pointerList[i].currentIndex]; const minVal = pointerList[minPointerPos].data[pointerList[minPointerPos].currentIndex]; if (currentVal < minVal) { minPointerPos = i; } } const targetPointer = pointerList[minPointerPos]; const currentMinVal = targetPointer.data[targetPointer.currentIndex]; // 基于有序性直接去重,不需要额外哈希表 if (currentMinVal !== lastAddedValue) { result.push(currentMinVal); lastAddedValue = currentMinVal; } targetPointer.currentIndex++; // 数组遍历完成后移除对应指针,减少后续遍历范围 if (targetPointer.currentIndex >= targetPointer.data.length) { pointerList.splice(minPointerPos, 1); } } return result; }
测试验证:使用示例输入
arrays = [[15, 30, 35, 40, 45, 50], [33, 36, 39, 42, 45, 48], [37, 38, 39, 40, 41, 42]]调用上述方法,输出结果完全匹配预期:[15, 30, 33, 35, 36, 37, 38, 39, 40, 41, 42, 45, 48, 50]
额外性能优化点
- 去重逻辑不需要额外维护哈希集合:因为所有输入数组都是有序的,重复值只会在归并过程的相邻候选值中出现,直接比对上一次加入结果集的值就能完成去重,省掉了哈希结构的内存开销和查重时间
- 针对超大数组数量的场景:可以把指针列表换成双向链表结构,避免频繁splice操作带来的数组元素移动开销,进一步降低大k场景下的运行成本
- 尽量避免在归并过程中反复扩容结果数组:可以提前估算所有输入数组的总长度,一次性给结果数组分配对应长度的内存,减少数组动态扩容的开销
内容的提问来源于stack exchange,提问作者parliament
相关产品推荐
相关产品推荐

