Skip to content

Commit 15e06b4

Browse files
committed
Add my impression
1 parent da9d916 commit 15e06b4

File tree

1 file changed

+151
-0
lines changed

1 file changed

+151
-0
lines changed

interview/Print_PrimeNumbers.md

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
# How to find prime Numbers efficiently
2+
3+
**Translator: [shazi4399](https://github.com/shazi4399)**
4+
5+
**Author: [labuladong](https://github.com/labuladong)**
6+
7+
The definition of a prime number seems simple,which is said to be prime number if it can be divided by 1 and itself.
8+
9+
However,don't think that the definition of prime numbers is simple. I am afraid that few people can write a prime-related algorithm that works really efficiently. Let's say you write a function like this:
10+
11+
```java
12+
// Returns several primes in the interval [2, n)
13+
int countPrimes(int n)
14+
15+
// E.g. countPrimes (10) returns 4
16+
// Because 2,3,5,7 is prime numbers
17+
```
18+
19+
How would you progrma this function? I think you maybe write like this:
20+
21+
```java
22+
int countPrimes(int n) {
23+
int count = 0;
24+
for (int i = 2; i < n; i++)
25+
if (isPrim(i)) count++;
26+
return count;
27+
}
28+
29+
// Determines whether integer n is prime
30+
boolean isPrime(int n) {
31+
for (int i = 2; i < n; i++)
32+
if (n % i == 0)
33+
// There are other divisibility factors
34+
return false;
35+
return true;
36+
}
37+
```
38+
39+
The time complexity is O (n ^ 2), which is a big problem.**First of all, the idea of using the isPrime function to assist is not efficient; and even if you want to use the isPrime function, there is computational redundancy in writing the algorithm**.
40+
41+
Let's briefly talk about **how to write an algorithm if you want to determine whether a number is prime or not**. Just slightly modify the for loop condition in the isPrim code above:
42+
43+
```java
44+
boolean isPrime(int n) {
45+
for (int i = 2; i * i <= n; i++)
46+
...
47+
}
48+
```
49+
50+
In other words, `i` does not need to traverse to` n`, but only to `sqrt (n)`. Why? let's take an example, suppose `n = 12`.
51+
52+
```java
53+
12 = 2 × 6
54+
12 = 3 × 4
55+
12 = sqrt(12) × sqrt(12)
56+
12 = 4 × 3
57+
12 = 6 × 2
58+
```
59+
60+
As you can see, the last two products are the reverse of the previous two, and the critical point of inversion is at `sqrt (n)`.
61+
62+
In other words, if no divisible factor is found within the interval `[[2, sqrt (n)]`, you can directly conclude that `n` is a prime number, because in the interval `[[sqrt (n), n] ` Nor will you find a divisible factor.
63+
64+
Now, the time complexity of the `isPrime` function is reduced to O (sqrt (N)), ** but we don't actually need this function to implement the` countPrimes` function. The above just hope that readers understand the meaning of `sqrt (n)`, because it will be used again later.
65+
66+
67+
### Efficient implementation `countPrimes`
68+
69+
The core idea of efficiently solving this problem is to reverse the conventional idea above:
70+
71+
First from 2, we know that 2 is a prime number, then 2 × 2 = 4, 3 × 2 = 6, 4 × 2 = 8 ... all are not prime numbers.
72+
73+
Then we found that 3 is also a prime number, so 3 × 2 = 6, 3 × 3 = 9, 3 × 4 = 12 ... are also impossible to be prime numbers.
74+
75+
Seeing this, do you understand the logic of this exclusion method a bit? First look at our first version of the code:
76+
77+
```java
78+
int countPrimes(int n) {
79+
boolean[] isPrim = new boolean[n];
80+
// Initialize the arrays to true
81+
Arrays.fill(isPrim, true);
82+
83+
for (int i = 2; i < n; i++)
84+
if (isPrim[i])
85+
// Multiples of i cannot be prime
86+
for (int j = 2 * i; j < n; j += i)
87+
isPrim[j] = false;
88+
89+
int count = 0;
90+
for (int i = 2; i < n; i++)
91+
if (isPrim[i]) count++;
92+
93+
return count;
94+
}
95+
```
96+
97+
If you can understand the above code, then you have mastered the overall idea, but there are two subtle areas that can be optimized.
98+
99+
First of all, recall the `isPrime` function that just judges whether a number is prime. Due to the symmetry of the factors, the for loop only needs to traverse` [2, sqrt (n)] `. Here is similar, our outer for loop only needs to traverse to `sqrt (n)`:
100+
101+
```java
102+
for (int i = 2; i * i < n; i++)
103+
if (isPrim[i])
104+
...
105+
```
106+
107+
In addition, it is difficult to notice that the inner for loop can also be optimized. Our previous approach was:
108+
109+
```java
110+
for (int j = 2 * i; j < n; j += i)
111+
isPrim[j] = false;
112+
```
113+
114+
This can mark all integer multiples of `i` as` false`, but there is still computational redundancy.
115+
116+
For example, when `n = 25` and` i = 4`, the algorithm will mark numbers such as 4 × 2 = 8, 4 × 3 = 12, and so on, but these two numbers have been marked by 2 × 4 and 3 × 4 that is `i = 2` and` i = 3`.
117+
118+
We can optimize it slightly so that `j` traverses from the square of` i` instead of starting from `2 * i`:
119+
120+
```java
121+
for (int j = i * i; j < n; j += i)
122+
isPrim[j] = false;
123+
```
124+
125+
In this way, the algorithm for counting prime numbers is efficiently implemented. In fact, this algorithm has a name, which called Sieve of Eratosthenes. Take a look at the complete final code:
126+
127+
```java
128+
int countPrimes(int n) {
129+
boolean[] isPrim = new boolean[n];
130+
Arrays.fill(isPrim, true);
131+
for (int i = 2; i * i < n; i++)
132+
if (isPrim[i])
133+
for (int j = i * i; j < n; j += i)
134+
isPrim[j] = false;
135+
136+
int count = 0;
137+
for (int i = 2; i < n; i++)
138+
if (isPrim[i]) count++;
139+
140+
return count;
141+
}
142+
```
143+
144+
**The time complexity of this algorithm is difficult to calculate**.It is obvious that the time is related to these two nested for loops. The operands should be:
145+
146+
n/2 + n/3 + n/5 + n/7 + ...
147+
= n × (1/2 + 1/3 + 1/5 + 1/7...)
148+
149+
In parentheses, ther is the inverse of the prime number .The final result is O(N * loglogN),and readers interested in this can refer to the time complexity of the algorithm
150+
151+
That is all about how to find prime Numbers.The seemingly simple problem does has a lot of details to polish

0 commit comments

Comments
 (0)