素数的性质:
1 如果一个正整数只有两个因子, 1和p,则称p为素数.
2 初等数学基本定理:任一大于1的自然数,要么本身是质数,要么可以分解为几个质数之积,且这种分解是唯一的。
1. 根据性质1,我们可以通过枚举法判断一个数是不是素数
2. 对于任意正整数a、b,如果a*b = c 且 a < Math.sqrt(n),则b > Math.sqrt(n)。所以,当我们将i从2遍历到Math.sqrt(n),就已经将所有的可能性都遍历过了。所以,我们可以将方法1进行改造
方法2:
此时,时间复杂度将为O(sqrt(n))。
3. 对于所有的偶数,都能被2整除,所以,偶数一定不是素数,所以在遍历的时候,i可以从3开始,每次增加2
方法3:
此时,时间复杂度O(sqrt(n)/2)。
4. 除去枚举法,剩下的就是先将N个素数列出来,然后进行二分查找,列举素数一般用打表法,原理是一个素数的倍数,肯定不是素数。
由观察可以知道,在内部for循环里面,会对之前已经筛选过的数据进行重复筛选,比如30这个数,i=2的时候,2*15=30会筛选一次,5*6=30,又会筛选一次。我们可以在可以被i整除的最小的素数的时候跳出筛选
方法5:
1 如果一个正整数只有两个因子, 1和p,则称p为素数.
2 初等数学基本定理:任一大于1的自然数,要么本身是质数,要么可以分解为几个质数之积,且这种分解是唯一的。
1. 根据性质1,我们可以通过枚举法判断一个数是不是素数
方法1
boolean isPrime(int n) {
if(n < 2) return false;
for(int i = 2; i < n; i++) {
if (n % i == 0) {
return false;
}
}
return true;
}
这种算法的复杂度为O(n)。
2. 对于任意正整数a、b,如果a*b = c 且 a < Math.sqrt(n),则b > Math.sqrt(n)。所以,当我们将i从2遍历到Math.sqrt(n),就已经将所有的可能性都遍历过了。所以,我们可以将方法1进行改造
方法2:
boolean isPrime(int n) {
if(n < 2) return false;
for(int i = 2, end = Math.sqrt(n); i <= end; i++) {
if (n % i == 0) {
return false;
}
}
return true;
}
此时,时间复杂度将为O(sqrt(n))。
3. 对于所有的偶数,都能被2整除,所以,偶数一定不是素数,所以在遍历的时候,i可以从3开始,每次增加2
方法3:
boolean isPrime(int n) {
if(n < 2) return false;
for(int i = 3, end = Math.sqrt(n); i <= end; i += 2) {
if (n % i == 0) {
return false;
}
}
return true;
}
此时,时间复杂度O(sqrt(n)/2)。
4. 除去枚举法,剩下的就是先将N个素数列出来,然后进行二分查找,列举素数一般用打表法,原理是一个素数的倍数,肯定不是素数。
boolean[] prime = new boolean[n];
int[] primes = new int[n];
int cnt = 0;
for (int i = 2; i < n; i++) {
prime[i] = true;
}
for (int i = 2; i < n; i++) {
if (prime[i]) {
primes[cnt++] = i;
for (int k=i*i; k<N; k+=i)
prime[k]=false;
}
}
由观察可以知道,在内部for循环里面,会对之前已经筛选过的数据进行重复筛选,比如30这个数,i=2的时候,2*15=30会筛选一次,5*6=30,又会筛选一次。我们可以在可以被i整除的最小的素数的时候跳出筛选
方法5:
boolean[] visit = new boolean[n + (int) Math.log10(n)];
int[] primes = new int[n];
int num = 0;
for (int i = 2; i <= n; ++i)
{
if (visit[i] == true)
{
num++;
primes[num] = i;
}
for (int j = 1; ((j <= num) && (i * primes[j] <= n)); ++j)
{
visit[i * primes[j]] = false;
if (i % primes[j] == 0) break; //此处是重点,避免了很多的重复判断,比如i=9,现在素数是2,3,5,7,进入二重循环,visit[2*9]=1;visit[3*9]=1;这个时候9%3==0,要跳出。因为5*9可以用3*15来代替,如果这个时候计算了,i=15的时候又会被重复计算一次,所以这里大量避免了重复运算。
}
}