Data structure and algorithm interview questions: Given non-negative integers m and n, calculate the number of prime numbers among the numbers not greater than m. (Hint: The principle of the algorithm is Essie sieve, linear sieve)

Data structure and algorithm interview questions: Given non-negative integers m and n, calculate the number of prime numbers among the numbers not greater than m. (Hint: The principle of the algorithm is Essie sieve, linear sieve)

Introduction: Data structure and algorithm interview question: Given non-negative integers m and n, calculate the number of prime numbers among the numbers not greater than m. (Hint: The principle of the algorithm is Essie sieve, linear sieve)

Algorithm ideas

Algorithm idea:

According to the meaning of the question, the question needs to calculate the number of prime numbers not greater than m. First, you need to judge whether an integer is a prime number, and then accumulate the number of prime numbers.

The most commonly used method of judging prime numbers is trial division. Assuming that you want to judge whether n is a prime number, you only need to try to divide it from 2 to n-1. If you find that there are factors other than 1 and itself, then n is not a prime number; otherwise n is Prime number. However, the time complexity O(n) required by this method is very high, which cannot meet the actual needs. And for maximum efficiency, you can use an Esperanto sieve or a linear sieve to find prime numbers.

Esperanto sieve:

Enumerate each number from 1 to m, and judge whether it is screened out by the previous number. If not, mark all multiples of the number as composite numbers (screened out). When implementing, prime numbers can be put into the container, and prime numbers that have been screened can be skipped when sifting out composite numbers, which can improve efficiency, and the time complexity is O ( nloglogn ) O(nloglogn)O(nloglogn)

Linear Sieve:

It is similar to the Esperanto sieve, but when sieving, small prime numbers are used to sieve composite numbers, and the remaining numbers that have not been sieved are prime numbers. For example, multiples of 2 will be marked as composite numbers for the first time, multiples of 3 will be marked as composite numbers for the second time, and so on. But it should be noted that a composite number may be screened by multiple prime numbers, so each number can only be marked once. Time complexity is O ( n ) O(n)O ( n )

Because the linear sieve method works better, the implementation of the linear sieve algorithm is given below:

#include <iostream>
#include <vector>

using namespace std;

int countPrimes(int n) {
    vector<bool> is_prime(n, true); // 初始化所有数都是质数
    vector<int> primes;             // 存储找到的质数

    for (int i = 2; i < n; ++i) {
        if (is_prime[i]) {         // 如果当前数仍然是质数
            primes.push_back(i);   // 将其加入质数数组
        }
        for (int j = 0; j < primes.size() && i * primes[j] < n; ++j) {
            // 遍历已有的质数进行筛选
            is_prime[i * primes[j]] = false;
            if (i % primes[j] == 0) break; // 当前数的质因子已经被筛选过了
        }
    }

    return primes.size();
}

int main() {
    int n = 10;
    int cnt = countPrimes(n);
    cout << cnt << endl; // 4

    return 0;
}

which is_prime[i]represents the number iiWhether itrue is a prime number, the initial default is . Enumerate each number starting from 2, if it is a prime number, add it to the prime number array, and filter out all its composite numbers. In specific implementation, when the current number is known to be a prime number, the prime number can be used to screen a larger composite number. In order to correctly and quickly find composite numbers for screening, we maintain an array of prime numbers, which stores all existing prime numbers. for each numberiii , we traverse the existing prime numbers and remove their multiples one by one. Note that when the prime factor exceedsn \sqrt nn , its multiple must be less than nnn , so the algorithm does not need to iterate over multiples of it. Finally, the prime number can be output.

  • java version
import java.util.ArrayList;
import java.util.List;

public class Main {
    
    

    public static int countPrimes(int n) {
    
    
        boolean[] isPrime = new boolean[n];
        List<Integer> primes = new ArrayList<>();
        for (int i = 2; i < n; ++i) {
    
    
            if (!isPrime[i]) {
    
    
                primes.add(i);
            }
            for (int j = 0; j < primes.size() && i * primes.get(j) < n; ++j) {
    
    
                isPrime[i * primes.get(j)] = true;
                if (i % primes.get(j) == 0) break;
            }
        }
        return primes.size();
    }

    public static void main(String[] args) {
    
    
        int n = 10;
        int cnt = countPrimes(n);
        System.out.println(cnt); // 4
    }
}

Guess you like

Origin blog.csdn.net/qq_51447496/article/details/131170917