我有n(n在1到100之间)排序的数字数组,每个数组都有m个元素(在我的情况下,m大约为1000)。我想将它们合并为一个排序的数组。
我可以想到两种可能性:
1.使用两个数组合并算法(如http://www.nczonline.net/blog/2012/10/02/computer-science-and-javascript-merge-sort/下面的merge()
函数)并迭代应用它(第1和第2,然后合并第1 - 第2和第3等)
function merge(left, right) {
var result = [],
il = 0,
ir = 0;
while (il < left.length && ir < right.length){
if (left[il] < right[ir]){
result.push(left[il++]);
} else {
result.push(right[ir++]);
}
}
return result.concat(left.slice(il)).concat(right.slice(ir));
}
merge()
函数概括为n个数组。在每次迭代中,我会选择尚未处理的n个第一个值的最小值,并将其附加到结果中。这两个算法在复杂性方面是否相同?我觉得两个算法都在o(m * n)。我是对的吗?
是否有任何表现考虑采取一个算法而不是另一个算法?我觉得1比2简单。
答案 0 :(得分:3)
使用优先级队列合并n个数组(例如,基于二进制堆) 总元素数是m * n,因此算法复杂度为O(m * n * Log(n))。 算法草图:
Add numbers 1..n to priority queue, using 1st element of every
array as sorting key
(you may also use pairs (first element/array number).
At every step -
J = pop_minimum
add current head of Jth array to result
move head of Jth array to the right
if Jth array is not exhausted, insert J in queue (with new sorting key)
第一个算法的复杂性是
2*m + 3*m+ 4*m+...+n*m = m * (n*(n-1)/2-1) = O(n^2 * m)
答案 1 :(得分:1)
这是一个老问题,但是为了后代:
两个算法的确为O(n * m)。在算法1中,您必须为每个m数组重新合并。在算法2中,您只进行了一次大合并,但是从m个数组中选择最小值仍然是线性的。
我要做的是实现合并排序的修改版本以获取O(mlogn)。
如果有人需要,代码可以在GitHub https://github.com/jairemix/merge-sorted上找到。
这个想法是修改算法1并成对而不是线性地合并每个数组。
因此,在第一次迭代中,您将array1与array2合并,array3与array4合并,等等。
然后在第二次迭代中,将array1 + array2与array3 + array4,array5 + array6与array7 + array8等合并。
例如:
// starting with:
[1, 8], [4, 14], [2, 5], [3, 7], [0, 6], [10, 12], [9, 15], [11, 13]
// after iteration 1:
[1, 4, 8, 14], [2, 3, 5, 7], [0, 6, 10, 12], [9, 11, 13, 15]
// after iteration 2
[1, 2, 3, 4, 5, 7, 8, 14], [0, 6, 9, 10, 11, 12, 13, 15]
// after iteration 3
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
在JS中:
function mergeSortedArrays(arrays) {
// while there are still unmerged arrays
while (arrays.length > 1) {
const result = [];
// merge arrays in pairs
for (let i = 0; i < arrays.length; i += 2) {
const a1 = arrays[i];
const a2 = arrays[i + 1];
// a2 can be undefined if arrays.length is odd, so let's do a check
const mergedPair = a2 ? merge2SortedArrays(a1, a2) : a1;
result.push(mergedPair);
}
arrays = result;
}
// handle the case where no arrays is input
return arrays.length === 1 ? arrays[0] : [];
}
请注意合并排序的相似性。实际上,在归并排序中,唯一的区别是n = m,因此您将从m个预排序的数组(每个数组分别包含1个项)开始。因此,合并排序的O(mlogm)复杂性。