LeetCode 0204 Count Primes
作者:互联网
1. 题目描述
2. Solution 1
1、思路分析
枚举。写个判断n是否为质数的函数。遍历n,计数。TLE
2、代码实现
package Q0299.Q0204CountPrimes;
// TLE
public class Solution {
public int countPrimes(int n) {
if (n < 3) return 0;
int cnt = 0;
for (int i = 2; i < n; i++) // 严格小于n
if (isPrime(i)) cnt++;
return cnt;
}
private boolean isPrime(int n) {
for (int i = 2; i * i <= n; i++)
if (n % i == 0) return false;
return true;
}
}
3、复杂度分析
时间复杂度: O(n sqrt{n})
空间复杂度: O(1)
3. Solution 2
1、思路分析
The Sieve of Eratosthenes
https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes
1》偶数一定不是素数,只有剩下一半奇数可能是素数。
2》从奇数i中剔除不是素数的数,要剔除的是i的奇数倍。
2.1》考虑筛选的start,需要从j = i*i开始,why? 在2 ~ i*i这个范围中,小于i*i的数都在比i小的时候筛过一遍了。
2.2》考虑筛选的步长,j += 2*i。如,i=3,则i的奇数倍为: 3 *3, 3*5, 3*7, ... 对于一般的i,i*i, i*(i+2), i*(i+4)
2、代码实现
package Q0299.Q0204CountPrimes;
public class Solution2 {
public int countPrimes(int n) {
if (n < 3) return 0;
boolean[] isPrime = new boolean[n];
// 偶数必定不是素数,只有剩下一半奇数可能是素数
int cnt = n / 2;
for (int i = 3; i * i < n; i += 2) {
if (isPrime[i]) continue; // 说明i已经是素数,且已经剔除过了
// 从奇数中剔除不是素数的数
// 要剔除的是 i 的 奇数倍
// 1) 为什么是 i * i开始呢?假设,此时i = 5
//那么开始剔除 j = 1 时就是本身,此时要么已经被剔除,要么就是素数,所以 1 不考虑
//当 j = 2 || j = 4时,乘积为偶数所以也不在我们考虑范围内
//当 j = 3时,我们考虑 3 * 5 但是这种情况已经是当 i = 3的时候被考虑进去了所以我们只要考虑之后的就可以了
// 2) 那么为什么 j = j + i * 2呢
//根据上面所说 我们从3开始考虑 3 * 3,3 * 5,3 * 7....只要 j < n 我们就剔除
//带入i : i * i, i * ( i + 2 ) , i * ( i + 4 )....
for (int j = i * i; j < n; j += 2 * i) {
if (!isPrime[j]) {
--cnt;
isPrime[j] = true;
}
}
}
return cnt;
}
}
3、复杂度分析
时间复杂度: O(n logn)
空间复杂度: O(n)
标签:Count,cnt,int,复杂度,素数,剔除,0204,Primes,isPrime 来源: https://www.cnblogs.com/junstat/p/16336407.html