Abstract: Interviewer: Do you know how to find prime numbers? Me: Find prime numbers?
Share this article from Huawei cloud community " lot of people do not know the right way to find prime numbers ", the original author: bigsai.
Preface
Today's interviewers are the nightmare of countless developers. It is true that not many interviewers can be beaten, because most interviewers really have so many tricks. But in the interview, we small survivors can't completely deny that we can only make a single point of breakthrough-let the interviewer shine on a certain question. No, let’s share it today.
In recent years, the algorithm post is not talking about internal scrolling, and the development post is also a bit internally scrolled. The requirements for developers are getting higher and higher. Interviewers are also deliberately "making things difficult". Interviewers like to go from shallow to deep, and always like to ask. A: Do you know why? Do you know the principle? such as. Moreover, in the past, only interviewers from big factories liked to ask about algorithms, and the employees of big factories have good foundations, and many even have ACM experience or system brushing experience. This is easy to understand, but now some small company interviewers are also open-mouthed and closed-mouthed xx algorithms and xx data structures. Tell me, this is no, I was really asked.
Find a prime number
In such a process, I was not surprised when the interviewer asked me algorithm questions. I realized that I realized the top ten sorting principles, complexity analysis, and handwriting of the code. I also learned the various operations of linked lists and trees. But suddenly It’s just that the surprised interviewer came up with a prime number question. Let me restore the scene:
Interviewer: Do you know how to find prime numbers?
Me: Find prime numbers?
Interviewer: Yes, it is to find prime numbers.
Me: It’s very simple. If you judge a number as a prime number, then there must be no two numbers (except itself and 1) multiplied to equal it. Just enumerate to see if there is a number that can be divisible by it. If If there is, then it is not a prime number, if not, then it is a prime number.
The interviewer showed a disappointed expression, saying that I was right, but did not answer the point, let me talk about it specifically.
Let’s start my performance:
First of all, the dumbest method to determine whether n is a prime number, which is whether the enumeration [2,n-1] is directly divisible by n. If so, then return false. This is not a prime number, otherwise it is a prime number. ,code show as below:
boolean isprime(int value){
for(int i=2;i<value;i++)
{
if(value%i==0)
{return false;}
}
return true;
}
The time complexity of this judgment of a prime number is O(n).
But in fact, this is too time-consuming, it is completely unnecessary, can optimize . If a number is not a prime number, then it must be the product of two numbers, and these two numbers are usually one larger and one smaller, and the smaller is less than or equal to the radical n, and the larger is greater than or equal to the radical n. We only need to enumerate the small The possible range, see if it can be divisible, then you can judge whether the number is a prime number. For example, 100=2 50=4 25=5 20=10 10 Just find the interval 2-10. There must be a corresponding one on the right, don't worry about it.
boolean isprime(int value)
{
for(int i=2;i*i<value+1;i++)
{
if(value%i==0)
{return false;}
}
return true;
}
The reason why it is less than value+1 here is to include the root sign, for example, 3*3=9. To include 3. This time complexity is O(sqrt(n)). Interviewer, I will draw you a picture to show you the difference:
Speaking of this, the interviewer smiled relievedly.
Interviewer: Not bad, well mastered the basics
Me: Brother, in fact, the essence of finding prime numbers is not here. This is too inefficient in many cases. For example, find all prime numbers less than n. What do you do?
Interviewer: It's okay to use the second method to find O(n*sqrt(n)) using an array.
Find multiple prime numbers
When looking for multiple prime numbers (prime numbers less than n), the above method is very cumbersome, because there are a lot of repeated calculations, because there are a lot of repeated calculations when calculating whether a multiple of a number is a prime number, if the number is relatively large Then there is more waste of space.
In this way, the concept of prime sieve was invented and used. The principle of sieve is to count prime numbers from the front and back through a recursion, filtering and sorting.
Eratosthenes sieve method
If we look at a number that is not a prime number, then the product of this number has no number that can be it, so we can operate according to this idea:
Enumerate directly from the front to the back. The unmarked position of the number must be a prime number. If the number is a prime number, then mark the multiple of this number (you don't need to calculate it next time you traverse). If it is not a prime number then proceed to the next step. In this way, the larger the value, the fewer the number of calculations, and the array can be used for judgment when performing specific operations. Therefore, the core idea of the Elder Sieve is to determine the multiple of a prime number as a composite number.
Assuming that all are prime numbers at the beginning and 2 is prime, then the multiples of 2 are not prime numbers; then traverse to 3 and mark the multiples of 3; the next is 5 (because 4 has been marked); until n-1. The specific process can be seen in the picture:
The specific code is:
boolean isprime[];
long prime[];
void getprime()
{
prime=new long[100001];//记录第几个prime
int index=0;//标记prime当前下标
isprime=new boolean [1000001];//判断是否被标记过
for(int i=2;i<1000001;i++)
{
if(!isprime[i])
{
prime[index++]=i;
}
for(int j=i+i;j<1000000;j=j+i)//他的所有倍数都over
{
isprime[j]=true;
}
}
}
The algorithm complexity of this sieve is O(nloglogn); don't underestimate this logn, a log with a larger data volume may be less than 0, and the time is ten times a hundred times or more.
Euler Sieve
The interviewer had already nodded in agreement, oh oh yeah, but it was not over yet. There is also a linear sieve-Euler sieve. Observing the above-mentioned Elbow sieve, there are many repeated calculations, especially the previous prime numbers. For example, the least common multiple of 2 and 3 is 6, and every 3 calculations of 2 will also encounter a multiple of 3, and Euler sieve is in The improvement on the basis of the Elbow sieve effectively avoids this double calculation.
What kind of thinking is it? That is, the Ehrlich sieve encounters a prime number and calculates its multiple to the end, while the Euler sieve only uses the multiplied by the known prime number to mark . If the prime number can be divided evenly, stop marking it.
In the implementation, two arrays are also used, one for storing real and effective prime numbers, and one for marking.
- When traversing to a number, if the number is not marked, then the number is stored in the array of prime numbers, and the corresponding subscript is increased by 1.
- Regardless of whether the number is prime or not, traverse the known prime number and mark the product value of it and the prime number. If the prime number is divisible by the current value i, stop the operation and proceed to the next round.
The specific implementation code is:
boolean isprime[];
int prime[];
void getprimeoula()// 欧拉筛
{
prime = new int[100001];// 记录第几个prime
int index = 0;
isprime = new boolean[1000001];
for (int i = 2; i < 1000001; i++) {
if (!isprime[i]) {
prime[index++] = i;
}
for (int j = 0; j < index && i * prime[j] <= 100000; j++){//已知素数范围内枚举
isprime[i * prime[j]] = true;// 标记乘积
if (i % prime[j] == 0)
break;
}
}
}
You may ask why if (i% prime[j] == 0) has to break.
If i%prime[j]==0, then i=prime[j]*k. k is an integer.
So if we go to the next round
i prime[j+1]=(prime[j] k) prime[j+1]=prime[j] (k prime[j+1]) when i=k prime[j+1 ] The two positions conflict and repeat the calculation, so once you encounter the divisible one, stop.
You can see this process, 6 only mark 12 but not 18, and 18 is marked by 9*2. For detailed understanding, you need to look at the code more and think about it. The process diagram will not be drawn! Euler's idea is to mark it when I am closer. The time complexity of Euler Sieve is O(n), because each number is only marked once.
The interviewer showed an expression of appreciation, and said a good sentence, the following is to talk about the daily routine, let me wait for the next interview!
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。