web-dev-qa-db-fra.com

Exemple de O (n!)?

Qu'est-ce qu'un exemple (en code) d'une fonction O (n!)? Il faut que le nombre d'opérations approprié soit exécuté en fonction de n; c'est-à-dire que je parle de la complexité du temps.

47
Derek Long

Voilà. C'est probablement l'exemple le plus trivial d'une fonction qui s'exécute dans O(n!) time (où n est l'argument de la fonction):

void nFacRuntimeFunc(int n) {
  for(int i=0; i<n; i++) {
    nFacRuntimeFunc(n-1);
  }
}
69
sepp2k

Un exemple classique est le problème du voyageur de commerce par recherche brutale.

S'il y a N villes, la méthode de la force brute essaiera chaque permutation de ces N villes pour trouver celle qui est la moins chère. Maintenant, le nombre de permutations avec N villes est N!, ce qui rend sa complexité factorielle (O(N!)).

37
codaddict

Il existe des problèmes, qui sont NP-complete (vérifiables dans un temps polynomial non déterministe). Cela signifie que si les entrées sont échelles, votre calcul nécessaire pour résoudre le problème augmente plus que beaucoup. 

Certains problèmes NP-hard sont: Problème de chemin hamiltonien ( open img ), Problème de voyageur de commerce ( open img )
Quelques NP-complete problèmes sont: Problème de satisfiabilité booléenne (samedi) ( ouvert img ), N-puzzle ( ouvert img ), Problème de sac à dos ( open img ), Problème d'isomorphisme de sous-graphique ( open img ), Problème de somme de sous-ensemble ( open img ), Problème de clique ( open img ), Problème de couverture de vertex ( open img ), Problème de set indépendant ( open img ), Problème de set dominant ( open img ), Problème de coloration des graphes ( open img ),

Source: lien 1 , lien 2

alt text
Source: link

6
Margus

Trouver le déterminant avec expansion par des mineurs.

Très bonne explication ici .

# include <cppad/cppad.hpp>
# include <cppad/speed/det_by_minor.hpp>

bool det_by_minor()
{   bool ok = true;

    // dimension of the matrix
    size_t n = 3;

    // construct the determinat object
    CppAD::det_by_minor<double> Det(n);

    double  a[] = {
        1., 2., 3.,  // a[0] a[1] a[2]
        3., 2., 1.,  // a[3] a[4] a[5]
        2., 1., 2.   // a[6] a[7] a[8]
    };
    CPPAD_TEST_VECTOR<double> A(9);
    size_t i;
    for(i = 0; i < 9; i++)
        A[i] = a[i];


    // evaluate the determinant
    double det = Det(A);

    double check;
    check = a[0]*(a[4]*a[8] - a[5]*a[7])
          - a[1]*(a[3]*a[8] - a[5]*a[6])
          + a[2]*(a[3]*a[7] - a[4]*a[6]);

    ok = det == check;

    return ok;
}

Code de ici . Vous trouverez également les fichiers .hpp nécessaires .

5
Jungle Hunter

Je pense que je suis un peu en retard, mais je trouve snailsort le meilleur exemple d’algorithme déterministe O (n!) Il trouve fondamentalement la permutation suivante d'un tableau jusqu'à ce qu'il le trie.

Cela ressemble à ceci:

template <class Iter> 
void snail_sort(Iter first, Iter last)
{
    while (next_permutation(first, last)) {}
}
5
Gabi Purcaru

Tout algorithme qui calcule toute la permutation d'un tableau donné est O (N!).

4
John

l'exemple le plus simple :)

pseudocode:

input N
calculate N! and store the value in a vaiable NFac - this operation is o(N)
loop from 1 to NFac and output the letter 'z' - this is O(N!)

voilà :)

En tant qu'exemple réel, pourquoi ne pas générer toutes les permutations d'un ensemble d'éléments?

3
Armen Tsirunyan

Dans Wikipedia

Résoudre le problème du voyageur de commerce via la recherche par force brute; trouver le déterminant avec expansion par des mineurs.

http://en.wikipedia.org/wiki/Big_O_notation#Orders_of_common_functions

2

En C #

Ne serait-ce pas O (N!) Dans la complexité de l'espace? parce que la chaîne en C # est immuable.

string reverseString(string orgString) {
    string reversedString = String.Empty;

    for (int i = 0; i < orgString.Length; i++) {
        reversedString += orgString[i];
    }

    return reversedString;
}
1
user623429

Vous avez raison, les appels récursifs devraient prendre exactement n! temps. Voici un code permettant de tester le temps factoriel pour n valeurs différentes. La boucle intérieure court pour n! temps pour différentes valeurs de j, la complexité de la boucle interne est donc Big O (n!)

public static void NFactorialRuntime(int n)
    {
        Console.WriteLine(" N   Fn   N!");
        for (int i = 1; i <= n; i++)  // This loop is just to test n different values
        {
            int f = Fact(i);
            for (int j = 1; j <= f; j++)  // This is Factorial times
            {  ++x; }
            Console.WriteLine(" {0}   {1}   {2}", i, x, f);
            x = 0;
        }
    }

Voici le résultat du test pour n = 5, il itère exactement le temps factoriel.

  N   Fn   N!
  1   1   1
  2   2   2
  3   6   6
  4   24   24
  5   120   120

Fonction exacte avec complexité temporelle n!

// Big O(n!)
public static void NFactorialRuntime(int n)
    {
        for (int j = 1; j <= Fact(i); j++) {  ++x; }
        Console.WriteLine(" {0}   {1}   {2}", i, x, f);
    }
1
techdips

La méthode récursive que vous avez probablement apprise pour prendre le déterminant d'une matrice (si vous avez utilisé l'algèbre linéaire) prend O (n!) Temps. Bien que je n'aie pas particulièrement envie de coder tout ça. 

0
user477556

@clocksmith Vous avez absolument raison. Ceci ne calcule pas n !. Ce n'est pas non plus de O (n!). Je l'ai couru collecté les données dans le tableau ci-dessous. Veuillez comparer les colonnes 2 et trois. (#nF est le nombre d'appels à nFacRuntimeFunc) 

n #nF n!

0    0      1
1    1      1
2    4      2
3    15     6
4    65     24
5    325    120
6    1956   720
7    13699  5040

Donc, clairement si exécute bien pire que O (n!). Vous trouverez ci-dessous un exemple de code pour calculer n! récursivement. vous remarquerez que son ordre est O(n).

int Factorial(int n)
{
   if (n == 1)
      return 1;
   else
      return n * Factorial(n-1);
}
0
user3416507

Bogosort est le seul "officiel" que j'ai rencontré qui s'aventure dans la région O (n!). Mais ce n’est pas un O (n!) Garanti, c’est de nature aléatoire.

0
MdaG