Javascript 在一个排序数组中合并多个预排序数组的最快方法
我正在寻找最快的方法将多个预排序数组合并到一个排序数组中,而无需重复 例如:Javascript 在一个排序数组中合并多个预排序数组的最快方法,javascript,Javascript,我正在寻找最快的方法将多个预排序数组合并到一个排序数组中,而无需重复 例如: const 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] 实际上,这些阵列要大得多,所以我正在寻找一种快速的方法来实现这一点 这个问题
const 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]
实际上,这些阵列要大得多,所以我正在寻找一种快速的方法来实现这一点
这个问题是关于性能的,我知道它可以用O(n log(n))中的concat和sort(n log(n))来完成,但是我正在寻找O(n)中未经测试的东西。我不认为我的代码是最优的,但我目前还没有找到更好的方法 进一步的小改进可能是:
- 对循环使用普通的
,而不是数组.prototype.reduce
- 删除达到“完成”状态的阵列(而不是将其标记为完成)
console.time(“创建数组”);
const arrays=Array.from({length:1000},({,row)=>{
返回数组。from({length:100000},({,i)=>row+i);
});
console.timeEnd(“创建数组”);
常量createMergedArray=(数组)=>{
控制台时间(“创建toProcess”);
const toProcess=arrays.map((数组,行)=>{
返回{done:false,行,列:0,数组};
});
console.timeEnd(“创建toProcess”);
const merged=[];
while(toProcess.some({done}=>!done)){
const scan=toProcess.reduce(
(附件,项目)=>{
如果(!item.done){
if(项目数组[项目列]<附件最小值){
acc.minimum=项目数组[项目列];
acc.rows=[项目行];
}else if(item.array[item.column]==附件最小值){
附件行推送(项目行);
}
}
返回acc;
},
{行:[],最小值:无穷大}
);
合并。推送(扫描。最小值);
scan.rows.forEach((row)=>{
const item=toProcess[行];
while(item.array[item.column]==扫描.最小值){
++项目.栏;
}
item.done=item.array.length==item.column;
});
}
返回合并;
};
控制台。时间(“合并”);
const merged=createMergedArray(数组);
控制台。时间结束(“合并”);
console.assert(
合并的.every((n,i,arr)=>n>arr[i-1]| | 0==i),
“未排序或发现重复项”
);
您没有提到数组的大小,所以我使用了1k行和100k列
如果您将数组(number[][]
)传递给createMergedArray
,它将为您提供:
- 按升序排序的唯一数字数组
- 了解这种方法是否适合您的数据大小
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"
);