面试题:求[2, n)之间的素数个数
题目:求[2, n)之间的素数个数
素数的定义:
素数是指大于1的自然数,除了1和它本身之外没有其他因数的数。也就是说,素数只能被1和它本身整除,不能被其他自然数整除。
解法1
最简单的实现思路是,实现素数判断函数,然后从2~n逐个判断,然后统计素数个数
public static int countPrimes(int n) { if(2== n){ return 1; } int count =0; for(int i=2;i<n;i++){ if(isPrime(i)){ count++; } } return count; } public static Boolean isPrime(int n) { for(int i=2;i<n;i++){ if(0 == n%i){ return Boolean.FALSE; } } System.out.println("prime=" + n); return Boolean.TRUE; }
解法2
观察非素数的特点,如6为非素数,它除了被1和6本身整除外,6=2*3=3*2 ,所以实际上述判断时我们判断i<sqrt[n]即可,则算法改造如下:
public static int countPrimes_2(int n) { if(2== n){ return 1; } int count =0; for(int i=2;i<n;i++){ if(isPrime_2(i)){ count++; } } return count; } public static Boolean isPrime_2(int n) { for(int i=2;i*i<=n;i++){ if(0 == n%i){ return Boolean.FALSE; } } System.out.println("prime=" + n); return Boolean.TRUE; }
解法3:
再观察一下素数的整数倍,都不是素数,比如2*2=4,2*3=6,2*4=8,2*5=10...都不是
则看可以改造算法如下:初始化所有元素都是素数,然后按照素数的整数倍不是素数赋值,然后再统计素数个数
public static int countPrimes_3(int n) { Boolean[] isPrimes = new Boolean[n]; Arrays.fill(isPrimes,Boolean.TRUE); for(int i=2;i<n;i++){ if(isPrimes[i]){ for(int j=2*i;j<n;j+=i){ isPrimes[j] = false; } } } int count =0; for(int i=2;i<n;i++){ if(isPrimes[i]){ count++; } } return count; }
解法4
结合2,3结论,i只要到sqrt[n]即可,而6=2*3=3*2是对称的,最终优化的算法如下
public static int countPrimes_4(int n) { Boolean[] isPrimes = new Boolean[n]; Arrays.fill(isPrimes,Boolean.TRUE); for(int i=2;i*i<n;i++){ if(isPrimes[i]){ for(int j=i*i;j<n;j+=i){ isPrimes[j] = false; } } } int count =0; for(int i=2;i<n;i++){ if(isPrimes[i]){ count++; } } return count; }
本文来自博客园,作者:life_start,转载请注明原文链接:https://www.cnblogs.com/yangh2016/p/18371360