Usted realmente encontrar números primos?

Usted realmente encontrar números primos?


Definición de los números primos parece muy simple, aunque sólo si un número es divisible por 1 y sí, entonces este número es primo.

Lianqi

No creo que la definición de los números primos es simple, en realidad me temo que no muchas personas pueden principales algoritmos eficientes de escritura relacionada. Por ejemplo, le permiten escribir una función como esta:

// 返回区间 [2, n) 中有几个素数 
int countPrimes(int n)

// 比如 countPrimes(10) 返回 4
// 因为 2,3,5,7 是素数

¿Cómo se escribe esta función? Creo que hay que escribir:

int countPrimes(int n) {
    int count = 0;
    for (int i = 2; i < n; i++)
        if (isPrim(i)) count++;
    return count;
}

// 判断整数 n 是否是素数
boolean isPrime(int n) {
    for (int i = 2; i < n; i++)
        if (n % i == 0)
            // 有其他整除因子
            return false;
    return true;
}

Tales palabras escritas complejidad de tiempo la ( norte 2 ) O (n ^ 2) , un gran problema. En primer lugar, se utiliza la función de ayudar a esPrimo idea no es suficiente y eficiente;

E incluso si se utiliza la función esPrimo, algoritmos de escritura también existen para calcular la redundancia.

ahorrador

Simplemente bajo el orden de llegada, si se desea determinar si un número no es primo, cómo escribir algoritmos. Justo por encima de modificar ligeramente el código isPrim para el ciclismo condiciones:

boolean isPrime(int n) {
    for (int i = 2; i * i <= n; i++)
        ...
}

En otras palabras, no tiene que pasar por an, y sólo necesito sqrt (n) puede ser. Por eso, damos un ejemplo, supongamos que n = 12.

12 = 2 × 6
12 = 3 × 4
12 = sqrt(12) × sqrt(12)
12 = 4 × 3
12 = 6 × 2

Se puede observar que el producto de los dos primeros dos, a su vez, invierta el punto crítico en sqrt (n).
En otras palabras, si [2, sqrt (n)] se encuentra dentro de este intervalo de factores divisibles, podemos concluir directamente que n es un número primo, porque en el intervalo [sqrt (n), n] no se encuentra para ser factor de divisible.

Ahora, el tiempo es una función de la complejidad de la esPrimo reduce a O (sqrt (N)), pero nos damos cuenta de countPrimes funcionan en realidad no necesitan esta función, más que esperanza de que los lectores a comprender el significado de sqrt (n), ya que, etc también se utilizará.

Mahayana

countPrimes implementación eficiente

El desarrollo del núcleo de una solución eficaz a este problema y pensamiento convencional anterior anti interés:
En primer lugar, desde el principio 2, sabemos que 2 es un número primo, entonces el 2 × 2 = 4, 3 x 2 = 6, 4 x 2 = 8 ... no puede ser un número primo.
A continuación, también encontramos 3 número primo, entonces el 3 × 2 = 6, 3 x 3 = 9, 3 x 4 = 12 ... tampoco son ser un número primo.

Ver aquí, si usted entiende un poco de la lógica de la exclusión de la misma? Nos fijamos en la primera versión del código:

int countPrimes(int n) {
    boolean[] isPrim = new boolean[n];
    // 将数组都初始化为 true
    Arrays.fill(isPrim, true);

    for (int i = 2; i < n; i++) 
        if (isPrim[i]) 
            // i 的倍数不可能是素数了
            for (int j = 2 * i; j < n; j += i) 
                    isPrim[j] = false;

    int count = 0;
    for (int i = 2; i < n; i++)
        if (isPrim[i]) count++;

    return count;
}

Si el código anterior se puede entender, entonces usted ha dominado toda la idea, pero hay dos áreas de menor importancia pueden ser optimizados.

Elevado periodo

En primer lugar, recuperar únicamente la determinación de si un número es una función primordial número esPrimo, debido al factor de simetría, que sólo necesita para atravesar el bucle de [2,sqrt(n)]suficiente. Aquí es similar, nuestro ciclo for exterior 只需要遍历到 sqrt(n):

for (int i = 2; i * i < n; i++) 
    if (isPrim[i]) 
        ...

Además, apenas se nota el interior para el bucle puede ser optimizado. Nuestro enfoque anterior es:

for (int j = 2 * i; j < n; j += i) 
    isPrim[j] = false;

Esto a su vez puede tener una bandera i múltiplo entero es falso, sigue existiendo un cálculo redundancia.

Por ejemplo n = 25, i = algoritmo marca 4 4 × 2 = 8,4 × 3 = 12 números, etc., pero las dos figuras han sido i = 2 e i = 3 de 2 × 4 y 3 × 4 puntos a.

Podemos optimizar un poco y dejar j Parto de recorrido cuadrado, en lugar de desde 2 * i start:

for (int j = i * i; j < n; j += i) 
    isPrim[j] = false;

Por lo tanto, el recuento privilegiada en la implementación eficiente del algoritmo, de hecho, este algoritmo tiene un nombre, se llama la criba de Eratóstenes. Mira el código final completo:

int countPrimes(int n) {
    boolean[] isPrim = new boolean[n];
    Arrays.fill(isPrim, true);
    for (int i = 2; i * i < n; i++) 
        if (isPrim[i]) 
            for (int j = i * i; j < n; j += i) 
                isPrim[j] = false;

    int count = 0;
    for (int i = 2; i < n; i++)
        if (isPrim[i]) count++;

    return count;
}

La complejidad de tiempo del algoritmo se considera más difícil, obviamente, con el tiempo para los dos bucle anidado sobre el que operando debe ser:
... N- / n-2 + / + 3 n- / n- + 5/7 + ... = n- × ( 1/3 + 1/2 + 1/5 + 1 / ... 7)
Entre paréntesis figura el número primario alternativo. El resultado final es la ( norte * l la sol l la sol norte ) O (N * loglogN) , los lectores interesados puede comprobar fuera de la complejidad de tiempo del algoritmo se prueba.

Publicados 126 artículos originales · ganado elogios 57 · Vistas a 90000 +

Supongo que te gusta

Origin blog.csdn.net/wolfGuiDao/article/details/104952718
Recomendado
Clasificación