什么是更快 - 将2个排序的数组合并为具有重复值的排序数组

时间:2017-04-24 14:53:54

标签: javascript arrays algorithm sorting time-complexity

我试图找出执行以下任务的最快方法:

编写一个接受两个数组作为参数的函数 - 每个数组都是一个排序的,严格升序的整数数组,并返回一个新的严格上升的整数数组,其中包含来自两个输入数组的所有值。

EG。合并[1,2,3,5,7]和[1,4,6,7,8]应该返回[1,2,3,4,5,6,7,8]。

由于我没有正式的编程教育,我的算法和复杂性有点陌生:)我已经有2个解决方案,但我不确定哪个更快。

解决方案1(它实际上使用第一个数组而不是创建一个新数组):

function mergeSortedArrays(a, b) {
  for (let i = 0, bLen = b.length; i < bLen; i++) {
    if (!a.includes(b[i])) {
      a.push(b[i])
    } 
  }
  console.log(a.sort());
}

const foo = [1, 2, 3, 5, 7],
      bar = [1, 4, 6, 7, 8];
mergeSortedArrays(foo, bar);

和解决方案2:

function mergeSortedArrays(a, b) {
  let mergedAndSorted = [];

  while(a.length || b.length) {
    if (typeof a[0] === 'undefined') {
      mergedAndSorted.push(b[0]);
      b.splice(0,1);
    } else if (a[0] > b[0]) {
      mergedAndSorted.push(b[0]);
      b.splice(0,1);
    } else if (a[0] < b[0]) {
      mergedAndSorted.push(a[0]);
      a.splice(0,1);
    } else {
      mergedAndSorted.push(a[0]);
      a.splice(0,1);
      b.splice(0,1);
    }
  }
  console.log(mergedAndSorted);
}

const foo = [1, 2, 3, 5, 7],
      bar = [1, 4, 6, 7, 8];
mergeSortedArrays(foo, bar);

有人可以帮助我解决这两种解决方案的时间复杂性吗?还有,还有另一个更快的解决方案吗?我应该使用reduce()吗?

2 个答案:

答案 0 :(得分:0)

你修改传递参数的第一个函数,这是不好的做法。 您可以通过以下方式完成此操作:

function mergeSortedArrays(a, b) {
    return a.concat(b.filter(el => !a.includes(el))).sort();
}

答案 1 :(得分:0)

复杂性还取决于您在代码中使用的方法。

1)常用于排序的算法是Quicksort(作为快速排序的变种进行内省)。

它具有O(n log n)复杂度,但是在输入已经排序的情况下,最坏情况可能仍然是O(n ^ 2)。所以你的解决方案有O(长度(b)+长度(a)+长度(b)log(长度(a)+长度(b)))运行时复杂度。

2)根据complexity of splice()上的这个问题,javascript函数最坏的情况是需要O(n)步(将所有元素复制到大小为n + 1的新数组)。所以你的第二个解决方案需要数组b 的长度乘以在拼接期间复制元素所需的n个步骤加上push()的时间。

对于在线性时间O(n + m)工作的好解,请参考此Java example并将其移植(即创建一个大小长度(a)+长度(b)的数组并通过indeces步进如图所示)。或者在答案的下方查看非常紧凑甚至更快的实现。