Skip to content

Commit f66698d

Browse files
committed
linear sieve
1 parent a1a67e1 commit f66698d

File tree

2 files changed

+29
-1
lines changed

2 files changed

+29
-1
lines changed

Common Algorithm and Theory/README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,8 @@ This personal Blog contains explanation and **Java library/template implementati
4646
- [动态规划, 状态机, 规则引擎 | Dynamic Programming, State Machine, Rule Engine](./动态规划与状态机.md) (动态规划本质上属于分治法的应用)
4747
- [前缀和, 差分, 树状数组, 线段树 | Prefix Sum, Difference, Binary Indexed Tree, Segment Tree](./前缀和与差分.md)
4848
- [记忆化搜索 | Memory Search](./记忆化搜索.md)
49-
- [埃氏筛法 | Sieve of Eratosthenes](../Leetcode%20Practices/algorithms/medium/204%20Count%20Primes.java) (时间复杂度 `O(N*loglogN)`)
49+
- [埃氏筛法 | Eratosthenes Sieve](../Leetcode%20Practices/algorithms/medium/204%20Count%20Primes.java) (向前动态规划+排除法,时间复杂度 `O(N*loglogN)`)
50+
- [线性筛法 | Linear Sieve](../Leetcode%20Practices/algorithms/medium/204%20Count%20Primes.java) (埃氏筛法、欧拉筛法的优化,时间复杂度 `O(N)`)
5051
- [倍增法 | Binary Lifting](./倍增法.md) (时间复杂度 - 预处理 `O(N*logN)`,之后查询 `O(logN)`) ([倍增法与二分法的区别](./倍增法.md#二分-vs-倍增))
5152
- [弗洛伊德算法 | Floyd-Warshall Algorithm](./弗洛伊德算法.md) (时间复杂度 `O(N^3)`)
5253
- [Kadane 算法 | Kadane's Algorithm](./Kadane算法.md) (时间复杂度 `O(N)`)

Leetcode Practices/algorithms/medium/204 Count Primes.java

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,33 @@ public int countPrimes(int n) {
3535

3636

3737

38+
// Other's Solution 2:
39+
class Solution {
40+
public int countPrimes(int n) {
41+
// 线性筛法 - by ChatGPT,保证每个合数都只被其最小质因数筛去(因为合数都可以表示为一组纯质数的乘积),而不被其他质数重复筛去,从而达成性能优化
42+
// 整个过程中,通过不断地更新最小质因数数组 minPrime,能够在时间复杂度为 O(n) 的情况下找到小于等于 n 的所有质数。
43+
// 相比于朴素的埃氏筛法,减少了许多不必要的标记操作,从而提高了效率。其核心思想是避免多次标记同一个数,使得整个算法的时间复杂度相对较低。
44+
// Time: O(N)
45+
int[] minPrime = new int[n];
46+
List<Integer> primes = new ArrayList<>();
47+
48+
for (int i = 2; i < n; i++) {
49+
if (minPrime[i] == 0) { // 意味着 i 在前面的迭代没被设置过,所以是质数
50+
minPrime[i] = i; // i 是当前正在处理的数,minPrime[i] 表示 i 的最小质因数
51+
primes.add(i);
52+
}
53+
54+
for (int j = 0; j < primes.size() && primes.get(j) <= minPrime[i] && i * primes.get(j) < n; j++) { // primes.get(j) <= minPrime[i]:确保 primes.get(j) 小于等于当前合数 i 的最小质因数
55+
minPrime[i * primes.get(j)] = primes.get(j); // 将 minPrime[i * primes.get(j)] 设置为 primes.get(j),表示合数 i * primes.get(j) 的最小质因数是 primes.get(j)
56+
}
57+
}
58+
59+
return primes.size();
60+
}
61+
}
62+
63+
64+
3865
// My Solution (Time Limit Exceeded):
3966
class MySolution {
4067
public int countPrimes(int n) {

0 commit comments

Comments
 (0)