有没有一种更有效的运行时方法来遍历此数组? (JavaScript)

时间:2020-01-05 16:30:46

标签: javascript arrays performance memory-efficient

因此,我只是想知道是否通过下面的这个简单函数将值赋给变量是否会失去运行时效率:

const biggestNumberInArray = (arr) => {
  let biggest = 0;
  for (item of arr) {
    biggest = (item > biggest) ? item : biggest;
  }
  return biggest;
}

在for循环中,每次迭代都很好地为变量 biggest 分配了一个值。因此,如果我改为写:

if (biggest < item) { biggest=item;};

功能会更有效吗?我真的没有什么大不了的,这个问题主要是理论上的,我想了解力学的工作原理。

谢谢!

2 个答案:

答案 0 :(得分:2)

考虑两种观点:

  1. 理论的角度,即考虑渐近复杂度,这没有什么区别。两种算法都将在线性时间-O(n)上运行,因为无论如何您都必须遍历数组。作业需要固定的时间。 if子句也需要固定的时间。一个恒定时间或两个恒定时间仍然是恒定时间。

  2. 实用的角度来看,这可能会有所不同,但可能并不相关,尤其是对于大型阵列。对于小阵列,相对差异可能更相关,但是由于时间短,我们通常不太在意它。

答案 1 :(得分:1)

我在jsbench.me上对以下5个函数进行了基准测试(链接指向保存的测试):

const data = [1,2,3,4,5,6,7,8,9,0,99,88,77,66,55,44,33,22,11]

const fn1 = xs => xs.reduce((acc, x) => acc > x ? acc : x, -Infinity)

const fn2 = xs => {
  let res = -Infinity
  for (const x of xs) res = x > res ? x : res
  return res
}

const fn3 = xs => {
  let res = -Infinity
  for (const x of xs) {
    if (x > res) res = x
  }
  return res
}

const fn4 = xs => xs.reduce((acc, x) => Math.max(acc, x), -Infinity)

const fn5 = ([x, ...xs], acc = -Infinity) =>
  x == undefined ? acc : fn5(xs, x > acc ? x : acc)

到目前为止,最快的功能是#1,它基于Array.prototype.reduce并且避免了任何重新分配。

功能#2-#4(包括您的原始功能和建议的可能提高性能的功能)始终比#1慢40-55%。 #4(reduceMath.max)似乎始终比#2和#3快20%。

最慢的函数(取决于递归)是#5,比#1慢80-90%。

Math.max(x, y)x > y ? x : y慢。

我在运行macOS 10.15.1(Catalina)和Chrome v79.0.3945.88(64bit)的2019 MacBook Pro上进行了测试。您可能会通过不同的测试设置获得不同的结果,但是我有理由相信,基于reduce并避免重新分配的解决方案将是大多数现代浏览器中最快的选择。