如何解决在一个排序数组中合并多个预排序数组的最快方法
我正在寻找将多个预先排序的数组合并为一个排序数组且没有重复项的最快方法。
例如:
const arrays = [
[15,30,35,40,45,50],[33,36,39,42,48],[37,38,41,42]
];
应该输出:
[15,33,37,48,50]
实际上这些数组要大得多,所以我正在寻找一种快速的方法来做到这一点。
这个问题是关于性能我知道它可以用 concat 和 sort 在 O(n log (n)) 但我正在寻找O(n)。
解决方法
未经测试。我不认为我的代码是最佳的,但我目前没有看到更好的方法来解决这个问题。
进一步的小改进可能是:
- 使用普通的
for
循环代替Array.prototype.reduce
- 移除达到“完成”状态的数组(而不是仅仅将它们标记为完成)
console.time("Creation of arrays");
const arrays = Array.from({ length: 1000 },(_,row) => {
return Array.from({ length: 100000 },i) => row + i);
});
console.timeEnd("Creation of arrays");
const createMergedArray = (arrays) => {
console.time("Creation of toProcess");
const toProcess = arrays.map((array,row) => {
return { done: false,row,column: 0,array };
});
console.timeEnd("Creation of toProcess");
const merged = [];
while (toProcess.some(({ done }) => !done)) {
const scan = toProcess.reduce(
(acc,item) => {
if (!item.done) {
if (item.array[item.column] < acc.minimum) {
acc.minimum = item.array[item.column];
acc.rows = [item.row];
} else if (item.array[item.column] === acc.minimum) {
acc.rows.push(item.row);
}
}
return acc;
},{ rows: [],minimum: Infinity }
);
merged.push(scan.minimum);
scan.rows.forEach((row) => {
const item = toProcess[row];
while (item.array[item.column] === scan.minimum) {
++item.column;
}
item.done = item.array.length === item.column;
});
}
return merged;
};
console.time("Merging");
const merged = createMergedArray(arrays);
console.timeEnd("Merging");
console.assert(
merged.every((n,i,arr) => n > arr[i - 1] || 0 === i),"Unsorted or duplicates found"
);
您没有提到数组的大小,所以我使用了 1k 行和 100k 列。
如果您将数组 (number[][]
) 传递给 createMergedArray
,它应该给您:
- 按升序排列的唯一数字数组
- 了解此方法是否适用于您的数据规模
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。