"Pour les petites valeurs de n, O (n) peut être traité comme si c'était O (1)"


26

J'ai entendu plusieurs fois que pour des valeurs suffisamment petites de n, O (n) peut être pensé / traité comme si c'était O (1).

Exemple :

La motivation pour le faire est basée sur l'idée incorrecte que O (1) est toujours meilleure que O (lg n), est toujours meilleure que O (n). L'ordre asymptotique d'une opération n'est pertinent que si, dans des conditions réalistes, la taille du problème devient réellement importante. Si n reste petit, alors chaque problème est O (1)!

Qu'est-ce qui est suffisamment petit? dix? 100? 1000? À quel moment dites-vous "nous ne pouvons plus traiter cela comme une opération gratuite"? Y a-t-il une règle d'or?

Il semble que cela puisse être spécifique à un domaine ou à un cas, mais existe-t-il des règles générales sur la façon de penser à ce sujet?


4
La règle d'or dépend du problème que vous souhaitez résoudre. Soyez rapide sur les systèmes embarqués avec n100 ? Publier dans la théorie de la complexité?
Raphael

3
En y réfléchissant davantage, il semble fondamentalement impossible de trouver une règle empirique unique, car les exigences de performances sont déterminées par votre domaine et ses exigences commerciales. Dans les environnements sans ressources limitées, n peut être assez grand. Dans les environnements sévèrement contraints, il peut être assez petit. Cela semble évident maintenant avec le recul.
rianjs

12
@rianjs Vous semblez confondre O(1)pour libre . Le raisonnement derrière les premières phrases est qu'il O(1)est constant , ce qui peut parfois être incroyablement lent. Un calcul qui prend mille milliards d'années indépendamment de l'entrée est un O(1)calcul.
Mooing Duck

1
Question connexe sur la raison pour laquelle nous utilisons les asymptotiques en premier lieu.
Raphael

3
@rianjs: soyez conscient des blagues du type "un pentagone est approximativement un cercle, pour des valeurs suffisamment grandes de 5". La phrase à propos de laquelle vous posez une question fait un point, mais comme elle vous a causé une certaine confusion, cela vaut peut-être la peine de demander à Eric Lippert dans quelle mesure ce choix exact de la formulation a eu un effet humoristique. Il aurait pu dire, "s'il y a une limite supérieure sur alors chaque problème est O ( 1 ) " et il a quand même été mathématiquement correct. "Petit" ne fait pas partie des mathématiques. nO(1)
Steve Jessop

Réponses:


21

Tous les ordres de grandeur impliquent un constant , plusieurs d'entre eux en fait. Lorsque le nombre d'éléments est suffisamment grand, cette constante n'a pas d'importance. La question est de savoir si le nombre d'éléments est suffisamment petit pour que cette constante domine.C

Voici une façon visuelle d'y penser.

entrez la description de l'image ici

Tous ont une constante de démarrage qui détermine leur point de départ sur l'axe Y. Chacun a également une constante critique dominant la vitesse à laquelle ils augmenteront.C

  • Pour , C détermine le temps.O(1)C
  • est vraiment C × n , où C détermine l'angle.O(n)C×nC
  • est en réalité ( C × n ) 2 , où C détermine la netteté de la courbe.O(n2)(C×n)2C

Pour déterminer quel algorithme vous devez utiliser, vous devez estimer l'endroit où les temps d'exécution se croisent. Par exemple, une solution avec un temps de démarrage élevé ou un C élevé perdra au profit d'une solution O ( n ) avec un temps de démarrage faible et un C faible pour un nombre d'éléments relativement important.O(1)CO(n)C

Voici un exemple réel. Vous devez déplacer un tas de briques à travers une cour. Vous pouvez les déplacer quelques-unes à la fois avec vos mains, ou aller chercher une énorme rétrocaveuse lente pour les soulever et les conduire en un seul voyage. Quelle est votre réponse s'il y a trois briques? Quelle est votre réponse s'il y en a trois mille?

Voici un exemple CS. Disons que vous avez besoin d'une liste qui est toujours triée. Vous pouvez utiliser un arbre qui se maintiendra dans l'ordre pour . Ou vous pouvez utiliser une liste non triée et trier à nouveau après chaque insertion ou suppression à O ( n log n ) . Parce que les opérations d'arborescence sont compliquées (elles ont une constante élevée) et que le tri est si simple (constante faible), la liste gagnera probablement des centaines ou des milliers d'éléments.O(logn)O(nlogn)

Vous pouvez observer ce genre de chose, mais en fin de compte, l'analyse comparative est ce qui le fera. Vous devez également surveiller le nombre d'articles que vous aurez généralement et atténuer le risque d'être remis plus. Vous aurez également besoin de documenter votre hypothèse comme «les performances se dégraderont rapidement sur éléments» ou «nous supposons une taille maximale définie de X ».XX

Étant donné que ces exigences sont susceptibles de changer, il est important de mettre ce type de décisions derrière une interface. Dans l'exemple d'arborescence / liste ci-dessus, n'exposez pas l'arborescence ou la liste. De cette façon, si vos hypothèses s'avèrent fausses ou si vous trouvez un meilleur algorithme, vous pouvez changer d'avis. Vous pouvez même faire un hybride et changer dynamiquement d'algorithmes à mesure que le nombre d'éléments augmente.


Cela n'a aucun sens de dire . Ce que vous signifie vraiment est que si le temps d' exécution est T = O ( 1 ) puis (dans de nombreux cas) T C . Si T = O ( n ) alors dans de nombreux cas T C n , ou plus formellement T = C n + o ( n ) . Etc. Notez, cependant, que dans d'autres cas, la constante C varie avecO(1)=O(C)T=O(1)TCT=O(n)TCnT=Cn+o(n)C , dans certaines limites. n
Yuval Filmus

@YuvalFilmus C'est pourquoi j'aime les graphiques.
Schwern

C'est de loin la meilleure réponse, le point est à quelle vitesse la fonction grandit.
Ricardo

1
Beau graphique, mais l' axe devrait vraiment être étiqueté "temps", pas "vitesse". y
Ilmari Karonen

1
Est le O(n2) est-elle vraiment une parabole, là? Il semble très plat pour les petits et très raide pour les grands n . nn
David Richerby

44

Cela s'appuie en grande partie sur les réponses déjà publiées, mais peut offrir une perspective différente.

Il est révélateur que la question traite de "valeurs suffisamment petites de n ". L'intérêt de Big-O est de décrire comment le traitement se développe en fonction de ce qui est en cours de traitement. Si les données en cours de traitement restent petites, il n'est pas pertinent de discuter du Big-O, car vous n'êtes pas intéressé par la croissance (ce qui ne se produit pas).

Autrement dit, si vous parcourez une distance très courte dans la rue, il peut être tout aussi rapide de marcher, d'utiliser un vélo ou de conduire. Il peut même être plus rapide de marcher s'il vous faudra du temps pour trouver vos clés de voiture, ou si votre voiture a besoin d'essence, etc.

Pour les petits n , utilisez ce qui vous convient.

Si vous faites un voyage à travers le pays, vous devez chercher des moyens d'optimiser votre conduite, votre consommation d'essence, etc.


5
"Pour les petits n, utilisez ce qui vous convient." - si vous exécutez souvent l'opération , choisissez la plus rapide (pour votre ). Voir aussi ici . n
Raphael

4
Grande métaphore!
Evorlor

1
D'un point de vue purement mathématique, la complexité asymptotique ne vous dit rien quand n < infinity.
Gordon Gustafson

15

La citation est plutôt vague et imprécise. Il y a au moins trois façons connexes d'interpréter ce texte.

Le point mathématique littéral derrière cela est que, si vous n'êtes intéressé que par des instances de taille jusqu'à une certaine limite, il n'y a qu'un nombre fini d'instances possibles. Par exemple, il n'y a qu'un nombre fini de graphiques sur une centaine de sommets. S'il n'y a qu'un nombre fini d'instances, vous pouvez, en principe, résoudre le problème en construisant simplement une table de recherche de toutes les réponses à toutes les instances possibles. Maintenant, vous pouvez trouver la réponse en vérifiant d'abord que l'entrée n'est pas trop grande (ce qui prend un temps constant: si l'entrée est plus longue que  k, il n'est pas valide), puis recherchez la réponse dans le tableau (ce qui prend un temps constant: il y a un nombre fixe d'entrées dans le tableau). Notez, cependant, que la taille réelle de la table est probablement incroyablement grande. J'ai dit qu'il n'y a qu'un nombre fini de graphes sur cent sommets et c'est vrai. C'est juste que le nombre fini est plus grand que le nombre d'atomes dans l'univers observable.

Un point plus pratique est que, lorsque nous disons que le temps d' exécution d'un algorithme est , cela signifie seulement qu'il est asymptotiquement c n 2  étapes, pour une constante  C . Autrement dit, il y a une constante n 0 telle que, pour tout n n 0 , l'algorithme prend environ c n 2 étapes. Mais peut-être que n 0 = 100 , 000 , 000Θ(n2) cn2Cn0nn0cn2n0=100,000,000et vous n'êtes intéressé que par des instances de taille beaucoup plus petite que cela. La limite quadratique asymptotique pourrait même ne pas s'appliquer à vos petites instances. Vous pourriez être chanceux et cela pourrait être plus rapide sur de petites entrées (ou vous pourriez ne pas être chanceux et le faire ralentir). Par exemple, pour les petits  , n 2 < 1000 n , vous préférez exécuter un algorithme quadratique avec de bonnes constantes qu'un algorithme linéaire avec de mauvaises constantes. Un exemple concret de ceci est que les algorithmes de multiplication matricielle asymptotiquement les plus efficaces (variantes de Coppersmith – Winograd , fonctionnant dans le temps O ( n 2.3729 ) ) sont rarement utilisés dans la pratique parce que Strassennn2<1000nO(n2.3729) algorithme est plus rapide à moins que vos matrices ne soient vraiment grandes.O(n2.8074)

Un troisième point est que, si  est petit, n 2 et même n 3  sont petits. Par exemple, si vous avez besoin de trier quelques milliers d'éléments de données et que vous ne devez les trier qu'une seule fois, tout algorithme de tri est assez bon: a Θ ( n 2 )nn2n3Θ(n2)l'algorithme n'aura encore besoin que de quelques dizaines de millions d'instructions pour trier vos données, ce qui ne prend pas beaucoup de temps sur un processeur capable d'exécuter des milliards d'instructions par seconde. OK, il y a aussi des accès à la mémoire, mais même un algorithme lent prendra moins d'une seconde, il est probablement préférable d'utiliser un algorithme simple et lent et de bien faire les choses plutôt que d'utiliser un algorithme complexe et rapide et de constater qu'il est ultra-rapide mais bogué et ne trie pas correctement les données.


4
Bien que des points parfaitement corrects et valides, je pense que vous avez manqué le point. Il semble qu'ils voulaient dire que parfois l'algorithme avec fonctionne mieux qu'un algorithme avec O ( 1 ) , pour des n s suffisamment petits . Cela se produit, par exemple, lorsque le premier a un temps de fonctionnement 10 n + 50 , tandis que le second s'exécute au temps 100000 . Ensuite, pour n suffisamment petit, il est en fait plus rapide d'utiliser le protocole O ( n ) . O(n)O(1)n10n+50100000nO(n)
Ran G.

@A sonné. Cela ne relève-t-il pas de mon deuxième cas? (Surtout si je le modifie pour dire quelque chose de plus comme "Un algorithme linéaire avec de bonnes constantes pourrait battre un algorithme constant / logarithmique avec de mauvaises constantes"?)
David Richerby

1
Il serait bon de mentionner explicitement l'importance des constantes lorsque n est petit. C'est quelque chose qui ne serait probablement pas venu à l'esprit de quelqu'un qui ne l'a jamais entendu auparavant.
Rob Watts

9

La notation Big-O ne dit vraiment que le comportement du grand arbitraire n. Par exemple, signifie qu'il existe une constante c> 0 et un entier n 0 tel que f ( n ) < c n 2 pour chaque n > n 0 .F(n)=O(n2)n0F(n)<cn2n>n0

Dans de nombreux cas, vous pouvez trouver une constante c et dire "Pour chaque n> 0, f (n) est approximativement ". Ce sont des informations utiles à avoir. Mais dans certains cas, ce n'est pas vrai. Si f (n) = n 2 + 10 18 , cela est totalement trompeur. Donc, ce n'est pas parce que quelque chose est O (n ^ 2) que vous pouvez éteindre votre cerveau et ignorer la fonction réelle.cn2n2+dix18

D'un autre côté, si vous ne rencontrez que les valeurs n = 1, 2 et 3, alors dans la pratique, cela ne fait aucune différence ce que f (n) fait pour n ≥ 4, vous devriez donc aussi considérer que f ( n) = O (1), avec c = max (f (1), f (2), f (3)). Et c'est ce que signifie suffisamment petit: si l'affirmation que f (n) = O (1) ne vous induit pas en erreur si les seules valeurs de f (n) que vous rencontrez sont "suffisamment petites".


5

Si ça ne pousse pas, c'est O (1)

La déclaration de l'auteur est un peu axiomatique.

Les ordres de croissance décrivent ce qui arrive à la quantité de travail que vous devez faire en Naugmentant. Si vous savez que cela Nn'augmente pas, votre problème est efficace O(1).

N'oubliez pas que O(1)cela ne signifie pas «rapide». Un algorithme qui nécessite toujours 1 trillion d'étapes pour terminer est O(1). Un algorithme qui prend de 1 à 200 étapes, mais jamais plus, l'est O(1). [1]

Si votre algorithme prend exactement des N ^ 3étapes et que vous savez que Ncela ne peut pas dépasser 5, il ne peut jamais dépasser 125 étapes, c'est donc efficace O(1).

Mais encore une fois, O(1)ne signifie pas nécessairement «assez vite». C'est une question distincte qui dépend de votre contexte. Si cela prend une semaine pour terminer quelque chose, vous ne vous souciez probablement pas si c'est techniquement O(1).


[1] Par exemple, la recherche dans un hachage est O(1), même si les collisions de hachage signifient que vous devrez peut-être parcourir plusieurs éléments dans un même compartiment, tant qu'il existe une limite stricte sur le nombre d'éléments pouvant être dans ce compartiment.


1
Tout cela semble valable, à l'exception de ceci: "Si votre algorithme prend exactement N ^ 3 étapes et que vous savez que N ne peut pas être supérieur à 5, il ne peut jamais prendre plus de 125 étapes, c'est donc O (1)". . Encore une fois, si un algorithme prend un entier et que mon support d'entier maximum est 32767, est-ce O (1)? Évidemment pas. Big-O ne change pas en fonction des limites des paramètres. C'est O (n) même si vous savez que 0 <n <3 car n = 2 prend deux fois plus de temps que n = 1.
JSobell

3
@JSobell Mais c'est O (1). S'il y a une limitation qui limite votre n pour f (n), cela signifie qu'il ne peut pas croître indéfiniment. Si votre n est limité par 2 ^ 15, votre grande fonction n ^ 2 est en fait g(n) = min(f(2^15), f(n))- qui est dans O (1). Cela dit, dans la pratique, les constantes importent beaucoup et il est clair que n peut devenir suffisamment grand pour qu'une analyse asymptotique soit utile.
Voo

2
@JSobell Ceci est similaire à la question de savoir si les ordinateurs sont vraiment "Turing Complete", étant donné qu'ils ne peuvent techniquement pas avoir un espace de stockage infini. Techniquement, mathématiquement, un ordinateur n'est pas une "vraie" machine de Turing. En pratique, il n'y a pas de "bande infinie", mais les disques durs se rapprochent suffisamment.
Kyle Strand

J'ai écrit un système de risque financier il y a plusieurs années qui impliquait n ^ 5 manipulations matricielles, donc j'avais une limite pratique de n = 20 avant que les ressources ne deviennent un problème.
JSobell

Désolé, appuyez sur Entrée trop tôt. J'ai écrit un système de risque financier il y a plusieurs années qui impliquait n ^ 5 manipulations matricielles, donc j'avais une limite pratique de n = 20 avant que les ressources ne deviennent un problème. Selon cette logique erronée, la fonction créée est O (1) parce que j'ai une limite de 20. Lorsque le client dit "Hmm, nous devrions peut-être la déplacer à 40 comme limite ... Ouaip, l'algorithme est O (1 ), ce n'est donc pas un problème "... C'est pourquoi les limites d'une entrée n'ont pas de sens. La fonction était O (n ^ 5), pas O (1), et c'est un exemple pratique de la raison pour laquelle Big-O est indépendant des bornes.
JSobell

2

Maintenant, je peux utiliser une table de hachage et avoir des recherches O (1) (en laissant de côté l'implémentation spécifique de la table de hachage), mais si j'avais par exemple une liste, j'aurais des recherches O (n). Compte tenu de cet axiome, ces deux sont les mêmes si les collections sont suffisamment petites. Mais à un moment donné, ils divergent ... quel est ce point?

En pratique, c'est le point où la construction de la table de hachage prend plus que l'avantage que vous retirez des recherches améliorées. Cela variera beaucoup en fonction de la fréquence à laquelle vous effectuez la recherche, par rapport à la fréquence à laquelle vous effectuez d'autres choses. O (1) vs O (10) n'est pas un gros problème si vous le faites une fois. Si vous le faites des milliers de fois par seconde, même cela compte (bien qu'au moins, cela compte à un rythme croissant de façon linéaire).


Si vous voulez être sûr, faites quelques expériences pour voir quelle structure de données est la meilleure pour vos paramètres.
Yuval Filmus

@Telastyn Yuval Filmus a raison, si vous voulez vraiment en être sûr. Je connais un nom de personne Jim, ses paramètres sont ok. Mais il n'a pas écouté des conseils comme celui de Yuval. Vous devriez vraiment écouter Yuval pour être sûr et en sécurité.
InformedA

2

Bien que la citation soit vraie (mais vague), elle comporte également des dangers. Imo, vous devriez regarder la complexité à n'importe quelle étape de votre application.

C'est trop facile à dire: hé, je n'ai qu'une petite liste, si je veux vérifier si l'élément A est dans la liste, je vais simplement écrire une boucle facile pour parcourir la liste et comparer les éléments.

Ensuite, votre copain programmeur doit utiliser la liste, voit votre fonction et est comme: hé je ne veux pas de doublons dans la liste, donc il utilise la fonction pour chaque élément ajouté à la liste.

(attention, c'est toujours un petit scénario de liste.)

3 ans plus tard, j'arrive et mon patron vient de faire une grosse vente: notre logiciel va être utilisé par un grand détaillant national. Avant, nous ne desservions que les petits magasins. Et maintenant, mon patron vient à moi en jurant et en criant, pourquoi le logiciel, qui a toujours "bien fonctionné" maintenant est terriblement lent.

Il s'avère que cette liste était une liste de clients, et nos clients n'avaient que peut-être 100 clients, donc personne ne l'a remarqué. L'opération de remplissage de la liste était essentiellement une opération O (1), car elle prenait moins d'une milliseconde. Eh bien, pas tant quand il y a 10 000 clients à ajouter.

Et des années après la mauvaise décision initiale O (1), l'entreprise a presque perdu un gros client. Tout cela à cause d'une petite erreur de conception / hypothèse des années auparavant.


Mais il illustre également une caractéristique importante de nombreux systèmes du monde réel: les «algorithmes» que vous apprenez en tant que premier cycle sont en fait des morceaux à partir desquels de vrais «algorithmes» sont fabriqués. Ceci est généralement fait allusion à; par exemple, la plupart des gens savent que le tri rapide est souvent écrit pour revenir au tri par insertion lorsque les partitions deviennent suffisamment petites, et que la recherche binaire est souvent écrite pour revenir à la recherche linéaire. Mais peu de gens réalisent que le tri par fusion peut bénéficier d'une recherche binaire.
Pseudonyme du

1

La motivation pour le faire est basée sur l'idée incorrecte que O (1) est toujours meilleur que O (lg n), est toujours meilleur que O (n). L'ordre asymptotique d'une opération n'est pertinent que si, dans des conditions réalistes, la taille du problème devient réellement importante.

Si j'ai deux algorithmes avec ces temps:

  • log (n) +10000
  • n + 1

Il existe alors un point où ils se croisent. Pour nplus petit que cela, l'algorithme "linéaire" est plus rapide, et pour nplus grand que cela, l'algorithme "logarithmique" est plus rapide. Beaucoup de gens font l'erreur de supposer que l'algorithme logarithmique est plus rapide, mais pour les petits n, ce n'est pas le cas.

Si n reste petit, alors chaque problème est O (1)!

Je suppose que ce que l'on veut dire ici est que si nest limité, alors chaque problème est O (1). Par exemple, si nous trions des entiers, nous pouvons choisir d'utiliser le tri rapide. O(n*log(n))évidemment. Mais si nous décidons qu'il ne peut jamais y avoir plus que des 2^64=1.8446744e+19entiers, alors nous savons que n*log(n)<= 1.8446744e+19*log(1.8446744e+19)<= 1.1805916e+21. Par conséquent, l'algorithme prendra toujours moins de 1.1805916e+21"unités de temps". Comme c'est un temps constant, nous pouvons dire que l'algorithme peut toujours être fait dans ce temps constant -> O(1). (Notez que même si ces unités de temps sont des nanosecondes, cela représente un grand total de plus de 37411 ans). Mais quand même O(1).


0

Je soupçonne que bon nombre de ces réponses manquent d'un concept fondamental. O (1): O (n) n'est pas identique à f (1): f (n) où f est la même fonction, car O ne représente pas une seule fonction. Même le joli graphique de Schwern n'est pas valide car il a le même axe Y pour toutes les lignes. Pour utiliser tous le même axe, les lignes devraient être fn1, fn2 et fn3, où chacune était une fonction dont les performances pouvaient être directement comparées aux autres.

J'ai entendu plusieurs fois que pour des valeurs suffisamment petites de n, O (n) peut être pensé / traité comme si c'était O (1)

Eh bien, si n = 1 sont-ils exactement les mêmes? Non. Une fonction permettant un nombre variable d'itérations n'a rien de commun avec une qui ne le fait pas, la notation big-O s'en fout, et nous non plus.

La notation Big-O est simplement là pour exprimer ce qui se passe lorsque nous avons un processus itératif, et comment les performances (temps ou ressources) se dégradent à mesure que 'n' augmente.

Donc, pour répondre à la vraie question ... Je dirais que ceux qui font cette affirmation ne comprennent pas correctement la notation Big-O, car c'est une comparaison illogique.

Voici une question similaire: si je boucle une chaîne de caractères et que je sais qu'en général mes chaînes seront inférieures à 10 caractères, puis-je dire que c'est l'équivalent de O (1), mais si mes chaînes étaient plus longues, alors je dirais que c'était O (n)?

Non, car une chaîne de 10 caractères prend 10 fois plus de temps qu'une chaîne de 1 caractère, mais 100 fois moins qu'une chaîne de 1000 caractères! C'est en marche).


En fait, si vous savez que votre entrée comprendra au plus 10 caractères, vous pouvez écrire unO(1)algorithme. Tout d'abord, vérifiez qu'il y a au plus 10 caractères; sinon, vous pouvez rejeter sans avoir à regarder le reste. Maintenant, si cela prendF(je) étapes pour traiter une entrée de je caractères, votre temps restant est donné par max{F(0),,F(dix)}. C'est une constante, qui estO(1).
David Richerby

Oui, et c'est un exemple où la notation Big-O est généralement mal comprise. Selon votre argument, si je sais que la valeur maximale de n est 1 000 000, alors ma fonction est O (1). En fait, ma fonction pourrait être au mieux O (1) et au pire O (n). Cette notation est utilisée pour décrire la complexité algorithmique, pas une implémentation concrète, et nous utilisons toujours la plus chère pour décrire un scénario, pas le meilleur. En fait, selon votre argument, chaque fonction unique qui permet n <2 est O (1)! :)
JSobell

Non. La notation Big-O est utilisée pour décrire le taux de croissance des fonctions. Ces fonctions pourraient être utilisées pour mesurer quoi que ce soit. Et je n'ai certainement pas soutenu que "chaque fonction qui permetn<2 [quoi que cela signifie] est O(1). "J'ai en fait soutenu que toute fonction qui a la propriété F(n)F(dix) pour tous n est O(1), ce qui est vrai.
David Richerby

Désolé, mais si vous dites que connaître les limites supérieures de n fait une fonction O (1), alors vous dites que la représentation notationnelle est directement liée à la valeur de n, et ce n'est pas le cas. Tout le reste que vous mentionnez est correct, mais suggérant que parce que n a des bornes, O (1) n'est pas correct. Dans la pratique, il y a des endroits où ce que vous décrivez peut être observable, mais nous regardons ici la notation Big-O, pas le codage fonctionnel. Encore une fois, pourquoi suggéreriez-vous que n ayant un maximum de 10 le rendrait O (1)? Pourquoi 10? Pourquoi pas 65535 ou 2 ^ 64?
JSobell

Cela dit, si vous écrivez une fonction qui remplit une chaîne à 10 caractères, puis boucle toujours sur la chaîne, alors c'est O (1) car n est toujours 10 :)
JSobell

0

Je pense que le texte que vous avez cité est assez imprécis (utiliser le mot "mieux" n'a généralement aucun sens à moins que vous ne fournissiez le contexte: en termes de temps, d'espace, etc.) Quoi qu'il en soit, je pense que l'explication la plus simple serait:

Si le temps d'exécution augmente avec la taille d'une entrée, ce n'est certainement pas O(1) et cela devrait être clair. O(1)ne veut pas dire rapide . Cela signifie simplement (en termes de complexité temporelle) que le temps d'exécution a une borne supérieure constante .

Maintenant, prenons un ensemble relativement petit de 10 éléments et avons quelques algorithmes pour le trier (juste un exemple). Supposons que nous conservions les éléments dans une structure qui nous fournit également un algorithme capable de trier les éléments en temps constant. Disons que nos algorithmes de tri peuvent avoir les complexités suivantes (avec une notation big-O):

  1. O(1)
  2. O(n)
  3. O(nlog(n))
  4. O(n2)

Quel algorithme choisiriez-vous? La première réponse qui me vient à l’esprit peut être «bien sûr, j’utiliserai leO(1)one! ", mais ce n'est pas nécessairement correct. Ce que vous oubliez en pensant ainsi, c'est que la notation big-O cache le facteur constant . Et si vous savez que votre ensemble est assez petit, alors ce facteur constant peut être beaucoup plus important que la complexité asympthotique.

Maintenant, «révélons» la véritable complexité de ces algorithmes de tri mentionnés ci-dessus (où «vrai» signifie ne pas cacher la constante), représentés par le nombre d'étapes nécessaires pour terminer (et supposons que toutes les étapes prennent le même temps):

  1. 200 pas
  2. 11n pas
  3. 4nlog(n) étapes (journal avec base 2)
  4. 1n2 pas

Si notre entrée est de taille 10, alors ce sont des quantités exactes d'étapes pour chaque algorithme mentionné ci-dessus:

  1. 200 pas
  2. 11×dix=110 pas
  3. 4×dix×3,32134 pas
  4. 1×100=100 pas

Comme vous le voyez, dans ce cas, l'algorithme apparemment pire avec une complexité asympthotique O(n2) est le plus rapide, battant les algorithmes avec O(1),O(n) et O(nlog(n))complexités asympthotiques. Le facteur constant caché par la notation big-O importe ici. À mon avis, cela ne signifie pas que nous pouvons traiterO(n2) mieux que O(1) (qu'est-ce que cela signifierait de toute façon?) Cela signifie que pour une entrée suffisamment petite (comme vous l'avez vu dans l'exemple), le O(n2) peut encore être plus rapide que O(1)à cause de la constante cachée. Et si la constante est relativement grande par rapport à la taille de l'entrée, elle peut avoir plus d'importance que la complexité asympthotique.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.