web-dev-qa-db-fra.com

Exemple de Big O of 2 ^ n

Je peux donc imaginer ce qu’est un algorithme qui a une complexité de n ^ c, juste le nombre de boucles for imbriquées. 

for (var i = 0; i < dataset.len; i++ {
    for (var j = 0; j < dataset.len; j++) {
        //do stuff with i and j
    }
}

Le journal est quelque chose qui scinde le jeu de données en deux à chaque fois, la recherche binaire le fait (vous ne savez pas exactement à quoi ressemble le code correspondant). 

Mais qu'est-ce qu'un exemple simple d'un algorithme qui est c ^ n ou plus précisément 2 ^ n. Est-ce que O (2 ^ n) est basé sur des boucles de données? Ou comment les données sont fractionnées? Ou quelque chose d'autre entièrement?

20
dlkulp

Les algorithmes avec le temps d'exécution O (2 ^ N) sont souvent des algorithmes récursifs qui résolvent un problème de taille N en résolvant de manière récursive deux problèmes plus petits de taille N-1.

Ce programme imprime par exemple tous les mouvements nécessaires pour résoudre le fameux problème "Tours de Hanoi" pour N disques en pseudo-code

void solve_hanoi(int N, string from_peg, string to_peg, string spare_peg)
{
    if (N<1) {
        return;
    }
    if (N>1) {
        solve_hanoi(N-1, from_peg, spare_peg, to_peg);
    }
    print "move from " + from_peg + " to " + to_peg;
    if (N>1) {
        solve_hanoi(N-1, spare_peg, to_peg, from_peg);
    }
}

Soit T(N) le temps nécessaire pour N disques.

On a:

T(1) = O(1)
and
T(N) = O(1) + 2*T(N-1) when N>1

Si vous développez à plusieurs reprises le dernier terme, vous obtenez:

T(N) = 3*O(1) + 4*T(N-2)
T(N) = 7*O(1) + 8*T(N-3)
...
T(N) = (2^(N-1)-1)*O(1) + (2^(N-1))*T(1)
T(N) = (2^N - 1)*O(1)
T(N) = O(2^N)

Pour comprendre cela, il suffit de savoir que certains modèles de la relation de récurrence conduisent à des résultats exponentiels. Généralement, T(N) = ... + C*T(N-1) avec C > 1 signifie O (x ^ N). Voir:

https://en.wikipedia.org/wiki/Recurrence_relation

21
Matt Timmermans

Pensez par exemple itérer sur tous les sous-ensembles possibles d'un ensemble. Ce type d'algorithme est utilisé par exemple pour un problème généralisé de sac à dos. 

Si vous avez du mal à comprendre comment itérer sur des sous-ensembles se traduit par O (2 ^ n), imaginez un ensemble de n commutateurs, chacun correspondant à un élément d'un ensemble. Chacun des commutateurs peut maintenant être activé ou désactivé. Pensez à "sur" comme étant dans le sous-ensemble. Remarque, combien de combinaisons sont possibles: 2 ^ n.

Si vous voulez voir un exemple dans le code, il est généralement plus facile de penser à la récursion ici, mais je ne peux pas penser od à tout autre exemple agréable et compréhensible pour le moment. 

10
Marandil
  int Fibonacci(int number)
 {
  if (number <= 1) return number;

  return Fibonacci(number - 2) + Fibonacci(number - 1);
 }

La croissance double avec chaque ajout à l'ensemble de données en entrée. La courbe de croissance d’une fonction O(2N) est exponentielle - elle commence très peu profondément, puis monte de façon météorique . Mon exemple de grand O (2 ^ n), mais est bien mieux:

public void solve(int n, String start, String auxiliary, String end) {
   if (n == 1) {
       System.out.println(start + " -> " + end);
   } else {
       solve(n - 1, start, end, auxiliary);
       System.out.println(start + " -> " + end);
       solve(n - 1, auxiliary, start, end);
   }

Dans cette méthode, le programme imprime tous les mouvements pour résoudre le problème "Tour de Hanoi" . Les deux exemples utilisent un problème récursif pour résoudre le problème et ont un temps de traitement important (2 ^ n).

1
darthir21

c ^ N = Toutes les combinaisons d'éléments n à partir d'un alphabet de taille c.

Plus spécifiquement, 2 ^ N est tous les nombres pouvant être représentés avec N bits.

Les cas courants sont implémentés de manière récursive, quelque chose comme:

vector<int> bits;
int N
void find_solution(int pos) {
   if (pos == N) {
     check_solution();
     return;
   }
   bits[pos] = 0;
   find_solution(pos + 1);
   bits[pos] = 1;
   find_solution(pos + 1);
}
0
Sorin

Voici un clip de code qui calcule la somme des valeurs de chaque combinaison de valeurs dans un tableau de produits (et value est une variable de tableau global):

fun boom(idx: Int, pre: Int, include: Boolean) {
    if (idx < 0) return
    boom(idx - 1, pre + if (include) values[idx] else 0, true)
    boom(idx - 1, pre + if (include) values[idx] else 0, false)
    println(pre + if (include) values[idx] else 0)
}

Comme vous pouvez le voir, c'est récursif. Nous pouvons insérer des boucles pour obtenir la complexité Polynomial et utiliser récursif pour obtenir la complexité Exponential.

0
boileryao

Voici deux exemples simples en python avec Big O/Landau (2 ^ N):

#fibonacci 
def fib(num):    
    if num==0 or num==1:
        return num
    else:
        return fib(num-1)+fib(num-2)

num=10
for i in range(0,num):
    print(fib(i))


#tower of Hanoi
def move(disk , from, to, aux):
    if disk >= 1:
        # from twoer , auxilart 
        move(disk-1, from, aux, to)
        print ("Move disk", disk, "from rod", from_rod, "to rod", to_rod)
        move(disk-1, aux, to, from)

n = 3
move(n, 'A', 'B', 'C')
0
grepit