Meilleure solution pour trouver des nombres avec exactement 3 diviseurs

J'étudiais de la programmation et j'ai trouvé un exercice pour écrire un algorithme trouvant des "nombres à trois" (nombres qui sont divisibles par exactement 3 Nombres). J'ai écrit ceci:

function threesomeNumber(N) {
    var found = 0;
    var i = 1;
    var numberOfDivisions = 1;
    while (found < N) {
        for (var j = 2; j <= i; j++) {
            if (i % j === 0) {
                numberOfDivisions++;
            }
        }
        if (numberOfDivisions === 3) {
            found++;
            console.log(found + " = " + i);
        }
        numberOfDivisions = 1;
        i++;
    }
}

Le problème est qu'il fonctionne un peu lentement et je me demandais si cela pouvait être fait plus rapidement. Est-ce que quelqu'un connaît une solution plus optimisée? Je veux qu'il trouve n numéros de trio consécutifs.

31
demandé sur Hermann Döppes 2015-12-08 21:40:42

4 réponses

Les seuls nombres à trois sont des carrés de nombres premiers (diviseurs 1, p, p^2). Il suffit de faire Erathostenes et retourner les carrés.

Preuve: Si il a un nombre impair de diviseurs il est connu pour être un carré. Puisque 1 et n^2 sont toujours des diviseurs de n^2, nous ne pouvons avoir qu'un diviseur de plus, c'est-à-dire N. tout diviseur de n serait un autre diviseur de n^2, donc n est premier.

Exemple (basé sur un code donné):

function threesomeNumber(N) {
var found = 0;
var i = 2;
var prime = true;
while (found < N) {
    // Naive prime test, highly inefficient
    for (var j = 2; j*j <= i; j++) {
        if (i % j === 0) {
            prime = false;
        }
    }
    if (prime) {
        found++;
        console.log(found + " = " + (i*i));
    }
    prime = true;
    i++;
  }
}
43
répondu Hermann Döppes 2015-12-08 19:16:20

Vous pouvez implémenter un algorithme basé sur le tamis D'Eratosthène . Le seul changement est que vous ne marquez pas les multiples de nombres premiers trouvés, mais les multiples de nombres trouvés qui ont au moins 3 diviseurs. La raison en est que vous pouvez être sûr que les multiples de ces nombres ont plus de 3 diviseurs.

EDIT: la solution de Hermann est la meilleure pour les "trios". Mon idée est plus générale et applicable pour "N-somes".

15
répondu Andrea Dusza 2015-12-08 19:07:54

Une solution plus optimisée consiste à trouver les premiers N nombres premiers et à les carré. L'idée derrière cela est que les nombres premiers sont divisibles par seulement deux nombres. Ainsi, les nombres divisibles par seulement trois nombres ont un diviseur supplémentaire qui doit être sa racine carrée. Il doit être un premier afin qu'il n'ajoute pas de diviseur supplémentaire aux diviseurs de nombres principaux.

function threesomeNumber(N){
    return firstPrimes(N).map(function(x){return x*x})
}

firstPrimes est une fonction qui renvoie les premiers nombres premiers N.

4
répondu MIE 2015-12-08 19:07:07

Voici un simple:

function threesomeNumber(N)
{
    var found = 0;
    var i = 1;
    var numberOfDivisions = 1;

    while(found < N)
    {
        for(var j = 2; j <= i; j++)
        {
            if(i % j === 0)
                numberOfDivisions++;

            // Stop trying if more that 3 Divisions are Found
            if(numberOfDivisions > 3)
               break;
        }

        if(numberOfDivisions === 3)
        {
            found++;
            console.log(found + " = " + i);
        }

        numberOfDivisions = 1;
        i++;
    }
}
2
répondu Boom 2015-12-08 19:09:36