判断一个数是不是质数的方法

如题:204. 计数质数

给定整数 n ,返回 所有小于非负整数 n 的质数的数量 。

示例 1:

输入:n = 10
输出:4
解释:小于 10 的质数一共有 4 个, 它们是 2, 3, 5, 7 。
示例 2:

输入:n = 0
输出:0
示例 3:

输入:n = 1
输出:0

提示:

0 <= n <= 5 * 106

 

方法一:

暴力枚举:

 1 class Solution {
 2     public int countPrimes(int n) {
 3         int ans = 0;
 4         for (int i = 2; i < n; ++i) {
 5             ans += isPrime(i) ? 1 : 0;
 6         }
 7         return ans;
 8     }
 9 
10     public boolean isPrime(int x) {
11         for (int i = 2; i * i <= x; ++i) {
12             if (x % i == 0) {
13                 return false;
14             }
15         }
16         return true;
17     }
18 }

 

 

 

方法二:

埃氏筛:

枚举没有考虑到数与数的关联性,因此难以再继续优化时间复杂度。接下来我们介绍一个常见的算法,该算法由希腊数学家厄拉多塞提出,称为厄拉多塞筛法,简称埃氏筛。

我们考虑这样一个事实:如果 x 是质数,那么大于 x 的 x 的倍数 2x,3x,… 一定不是质数,因此我们可以从这里入手。

我们设 isPrime[i] 表示数 i 是不是质数,如果是质数则为 1,否则为 0。从小到大遍历每个数,如果这个数为质数,则将其所有的倍数都标记为合数(除了该质数本身),即 0,这样在运行结束的时候我们即能知道质数的个数。

这种方法的正确性是比较显然的:这种方法显然不会将质数标记成合数;另一方面,当从小到大遍历到数 x 时,倘若它是合数,则它一定是某个小于 x 的质数 y 的整数倍,故根据此方法的步骤,我们在遍历到 y 时,就一定会在此时将 x 标记为 isPrime[x]=0。因此,这种方法也不会将合数标记为质数。

当然这里还可以继续优化,对于一个质数 x,如果按上文说的我们从 2x 开始标记其实是冗余的,应该直接从 x⋅x ,开始标记, x(x+1), x(x+2)因为 2x,3x,… 这些数一定在 x 之前就被其他数的倍数标记过了,例如 2 的所有倍数,3 的所有倍数等。

 1 class Solution {
 2     public int countPrimes(int n) {
 3         int[] isPrime = new int[n];
 4         Arrays.fill(isPrime, 1);
 5         int res = 0;
 6         for(int i=2; i<n; i++){
 7             if(isPrime[i]==1){
 8                 res+=1;
 9                 if((long)i*i < n){
10                     for (int j = i*i;  j<n; j+=i){
11                         isPrime[j] = 0;
12                     }
13                 }
14             }
15         }
16         return res;
17     }
18 }

 

 

 

 

方法三:线性筛

 

 

 

 

 1 class Solution {
 2     public int countPrimes(int n) {
 3         List<Integer> list = new ArrayList<>();
 4         int[] isPrime = new int[n];
 5         Arrays.fill(isPrime, 1);
 6         for (int i=2; i<n; i++){
 7             if(isPrime[i] == 1){
 8                 list.add(i);
 9             }
10             for (int j=0; j<list.size() && i*list.get(j)<n; j++){
11                 isPrime[i*list.get(j)] = 0;
12                 if(i%list.get(j) == 0){
13                     break;
14                 }
15             }
16         }
17         return list.size();
18     }
19 }

 

posted @ 2022-04-05 22:04  r1-12king  阅读(1067)  评论(0编辑  收藏  举报