素数:只能被1和它本身整除
试除法
试除法的时间复杂度为O(n*sqrt(n)),空间复杂度为O(1),这已经是一种比较高效的解决方案了。
n如果不是质数,那么能整除的数一定与根号n。基于此缩小循环比较范围,并且一旦找到可以整除的立即退出循环。
//打印n以内的质数
//素数:只能被1和它本身整除
function printPrimes(target) {for (let i = 2; i <= target; i++) {let count = 0;for (let j = 2; j <= Math.sqrt(i); j++) {if (i % j === 0) {count++;break;}}if (count == 0) {console.log(i);}}
}
printPrimes(1000);
试除法优化
进一步优化时间复杂度,可以考虑使用更高级的算法,比如埃拉托斯特尼筛法(Sieve of Eratosthenes)。这种算法可以在O(n*log(log(n)))的时间复杂度内找出小于等于n的所有质数,比试除法更加高效。
思想:如果n不是质数,那n^2肯定不是质数,n*(n+m)肯定也不是质数。由此可预先把后面的非质数找出来。n*(n+m-1)和n*(n+m)两个相邻的非质数中间差了n步长。因此第二个循环j+=i。
function printPrimes(target) {let isPrime = new Array(target + 1).fill(true);isPrime[0] = false;isPrime[1] = false;for (let i = 2; i <= Math.sqrt(target); i++) {if (isPrime[i]) {for (let j = i * i; j <= target; j += i) {isPrime[j] = false;}}}for (let i = 2; i <= target; i++) {if (isPrime[i]) {console.log(i);}}
}printPrimes(1000);
创建target+1长度的数组,数组下标对应1-target范围整数。数组下标0不使用。
初始化默认isPrime都是true。找到i可以整除的数时,改变isPrime为false
从2开始,2是质数,2的平方4肯定不是质数,6、8、10.。。都不是质数
i=3 3s是质数,3的平方9不是质数,9+3不是质数,9+6不是质数。3(3+m)
时间复杂度为O(n*log(log(n))),空间复杂度为O(n)。这种方法在处理大量质数时会比试除法更加高效。