web-dev-qa-db-fra.com

Big O, quelle est la complexité de la somme d'une série de n nombres?

J'ai toujours pensé à la complexité de:

1 + 2 + 3 + ... + n est O (n), et la somme de deux matrices n par n serait O (n ^ 2).

Mais aujourd’hui, j’ai lu dans un manuel: "Par la formule de la somme des n premiers entiers, c’est n (n + 1)/2" et ensuite: n, et donc O (n ^ 2).

Qu'est-ce que j'oublie ici? 

24
user1032613

La notation big O peut être utilisée pour déterminer le taux de croissance de la fonction any.

Dans ce cas, il semble que le livre ne parle pas de la complexité temporelle du calcul de la valeur, mais de la valeur elle-même. Et n(n+1)/2 est O(n^2).

16
svick

Vous confondez la complexité de runtime et la taille (complexité) de result.

Le temps d'exécution de sommation, l'un après l'autre, le premier n nombre consécutif est bien O (n).1

Mais la complexité du résultat, c’est la taille de «somme de 1 à n» = n(n - 1)/2 est O (n ^ 2).


1 Mais pour des nombres arbitrairement grands, cela est simpliste, car l’ajout de grands nombres prend plus de temps que l’ajout de petits nombres. Pour une analyse d'exécution précise, vous devez en effet tenir compte de la taille du résultat. Cependant, cela n’est généralement pas pertinent en programmation, ni même en informatique purement théorique. Dans les deux domaines, la somme de nombres est généralement considérée comme une opération O (1) sauf si le domaine l'exige explicitement (c'est-à-dire lorsque vous implémentez une opération pour une bibliothèque bignum).

8
Konrad Rudolph

n (n + 1)/2 est le moyen rapide de sommer une suite consécutive de N nombres entiers (à partir de 1). Je pense que vous confondez un algorithme avec la notation big-oh!

Si vous le considérez comme une fonction, alors la grande complexité de cette fonction est O (1):

 public int sum_of_first_n_integers (int n) {
 return (n * (n + 1))/2; 
} 

L'implémentation naïve aurait une grande complexité de O (n).

public int sum_of_first_n_integers(int n) {
  int sum = 0;
  for (int i = 1; i <= n; i++) {
    sum += n;
  }
  return sum;
}

Même en regardant chaque cellule d'une matrice n-par-n, on a O (n ^ 2), puisque la matrice a n ^ 2 cellules.

7
Julius Musseau

Il n'y a pas vraiment de complexité de problème, mais plutôt de complexité d'algorithme.

Dans votre cas, si vous choisissez de parcourir tous les nombres, la complexité est, en effet, O(n).

Mais ce n'est pas l'algorithme le plus efficace. Une méthode plus efficace consiste à appliquer la formule - n*(n+1)/2, qui est constante et, par conséquent, à la complexité est O(1).

2
Luchian Grigore

Vous avez une formule qui ne dépend pas du nombre de nombres ajoutés, donc c'est un algorithme à temps constant , ou O (1).

Si vous ajoutez chaque nombre un à la fois, alors c'est bien O (n). La formule est un raccourci. c'est un algorithme différent, plus efficace. Le raccourci fonctionne lorsque les nombres ajoutés sont tous 1 .. n . Si vous avez une séquence de nombres non contigus, la formule de raccourci ne fonctionne pas et vous devrez revenir à l'algorithme un par un.

Rien de tout cela ne s'applique à la matrice des nombres, cependant. Pour ajouter deux matrices, c’est toujours O (n ^ 2) car vous ajoutez n ^ 2 paires de nombres distincts pour obtenir une matrice de n ^ 2 résultats.

1
Rob Kennedy

Il y a une différence entre la somme de N entiers arbitraires et la somme de N qui sont tous alignés. Pour 1 + 2 + 3 + 4 + ... + N, vous pouvez tirer parti du fait qu’elles peuvent être divisées en paires avec une somme commune, par exemple. 1 + N = 2+ (N-1) = 3+ (N-2) = ... = N + 1. C'est donc N + 1, N/2 fois. (S'il y a un nombre impair, l'un d'eux ne sera pas associé, mais avec un peu d'effort, vous pouvez voir que la même formule est valable dans ce cas.)

Ce n'est pas O (N ^ 2), cependant. C'est juste une formule qui utilise N ^ 2, en fait O (1). O (N ^ 2) signifierait (à peu près) que le nombre de pas pour le calculer augmente comme N ^ 2, pour le grand N. Dans ce cas, le nombre de pas est le même quel que soit le N.

0
Tim Goodman

la réponse de la somme des séries de n naturelles peut être trouvée de deux manières. La première consiste à ajouter tous les chiffres en boucle. dans ce cas, l'algorithme est linéaire et le code sera comme ça

 int sum = 0;
     for (int i = 1; i <= n; i++) {
     sum += n;
   }
 return sum;

il est analogue à 1 + 2 + 3 + 4 + ...... + n. dans ce cas, la complexité de l'algorithme est calculée en tant que nombre d'opérations d'addition effectuées, soit 0 (n).

la seconde façon de trouver la réponse à la somme des séries de n nombres naturels est la formule la plus forte n * (n + 1)/2. cette formule utilise la multiplication au lieu de l’addition répétitive. l'opération de multiplication n'a pas de complexité temporelle linéaire. il existe différents algorithmes disponibles pour la multiplication, dont la complexité temporelle varie de O (N ^ 1,45) à O (N ^ 2). Par conséquent, en cas de multiplication, la complexité dépend de l'architecture du processeur. mais aux fins de l'analyse, la complexité temporelle de la multiplication est considérée comme étant O (N ^ 2). par conséquent, quand on utilise la seconde façon de trouver la somme, la complexité temporelle sera O (N ^ 2). 

ici, l'opération de multiplication n'est pas la même que l'opération d'addition. Si quelqu'un a une connaissance du sujet d'organisation informatique, il peut facilement comprendre le fonctionnement interne des opérations de multiplication et d'addition. Le circuit de multiplication est plus complexe que le circuit additionneur et nécessite un temps beaucoup plus long que celui-ci pour calculer le résultat. la complexité temporelle de la somme des séries ne peut donc pas être constante.

0
Ashok