对于采用整数n
并返回前n
个素数的数组的函数,我们有:
function nPrimes(n) {
let primes = [];
for(let i = 3; primes.length < n - 1; i += 2) {
if (primes.every(prime => i % prime !== 0)) {
primes.push(i);
}
}
primes.unshift(2);
return primes;
}
我不确定此算法的复杂程度。看来至少是二次的,因为every
调用给运行时复杂度增加了一个n
,其中n是给定迭代中素数数组的大小。最后的unshift
添加了一个n
,但这是无关紧要的,因为它会因前导系数而相形见f。
后续工作是,有没有更有效的方法来生成这样的数组?
答案 0 :(得分:0)
此计算非常艰巨。
外部循环执行n
次,并为从every
到第3
个素数的所有奇数调用n
构造。
如果every
构造确实测试了列表中的所有素数,则总工作量将与k.(P[k+1]-P[k]) = k.G[k]
的总和成比例,其中P[k]
是k
-第一个素数和G[k]
之间的距离直到下一个素数(找到第k
个素数时,列表中包含k
个元素,并进行测试直到下一个素数)。>
根据素数定理,我们知道“平均”间隙长度约为log P[k]
,本身约为log(k log k) = log k + log log k
。然后求和得出O(n.log n)
。
现在,如果every
构造在满足错误条件时立即停止,则可以降低成本。实际上,搜索将在被测数字的第一个素数处停止,总工作量将与所有P[n] ~ n log n
之前的所有奇数的第一个素数的索引之和成比例。
从网络搜索看来,整数的第一个质数因子的分布遵循1 / P[k] log P[k]
中第k
个质数,即1 / k.log k.log(k.log k)
的定律,我们需要使用m
对所有整数k ~ m / log m
求和。既不严格也不容易。