Comment sait-on quelle notation de l'analyse de la complexité temporelle utiliser?

91

Dans la plupart des classes d'introduction aux algorithmes, des notations telles que (Big O) et sont introduites, et un étudiant apprendra généralement à utiliser l'une de celles-ci pour rechercher la complexité temporelle.ΘOΘ

Cependant, il existe d'autres notations, telles que , et . Existe-t-il des scénarios spécifiques dans lesquels une notation serait préférable à une autre?Ω ωoΩω

Jack H
la source
2
ce n'est pas tellement préférable que applicable ...
vzn

Réponses:

76

Vous faites référence à la notation Landau . Ils ne sont pas des symboles différents pour la même chose mais ont des significations complètement différentes. Laquelle est "préférable" dépend entièrement de la déclaration souhaitée.

f g f o ( g ) <fO(g) signifie que croît au plus vite que , de manière asymptotique et jusqu’à un facteur constant; Pensez-y comme un . est la forme la plus stricte, c'est-à-dire .fgfo(g)<

f g ω f Ohm ( g ) g O ( f )fΩ(g) a la signification symétrique: grandit au moins aussi vite que . est son cousin plus strict. Vous pouvez voir que est équivalent à .fgωfΩ(g)gO(f)

f g f O ( g ) Ohm ( g ) f ~ g Θ OfΘ(g) signifie que croît à peu près aussi vite que ; officiellement . (égalité asymptotique) est sa forme la plus forte. Nous entendons souvent lorsque nous utilisons .fgfO(g)Ω(g)fgΘO

Notez que et ses frères sont des classes de fonctions . Il est important d'être très conscient de cela et de leurs définitions précises (qui peuvent différer en fonction de la personne qui parle) lors de l'utilisation de l'arithmétique avec elles.O(g)

Lorsque vous faites la preuve, veillez à travailler avec votre définition précise. Il existe de nombreuses définitions pour les symboles de Landau autour (toutes avec la même intuition de base), dont certaines sont équivalentes sur certains ensembles sur des fonctions mais pas sur d'autres.

Lecture suggérée:

Si vous souhaitez utiliser la notation Landau de manière rigoureuse et saine, vous pouvez être intéressé par les travaux récents de Rutanen et al. [1]. Ils formulent des critères nécessaires et suffisants pour la notation asymptotique, tels que nous les utilisons en algorithmique, montrent que la définition commune ne les respecte pas et fournissent une définition exploitable.


  1. Une définition générale de la notation O pour l'analyse algorithmique par K. Rutanen et al. (2015)
Raphaël
la source
5
Je veux juste souligner que bien que agisse comme et agisse comme , il existe des différences; il n’est pas difficile de trouver les fonctions et telles que et . OΩgffO(g)fΩ(g)
Zach Langley
1
+1 pour la mention des classes de fonctions. Des choses comme et apparaissent partout dans les journaux et les livres, ce qui peut être déroutant pour les personnes confrontées à ces notations pour la première fois. o(1)Ω(2n)
Janoma
7
@ZachLangley Ce que vous dites est très vrai. Il n'y a pas d'ordre total ici. Il est probablement dangereux de , mais je pense que cela sert à la construction de l'intuition.
Raphaël
42

Big O: limite supérieure

"Big O" ( ) est de loin le plus commun. Lorsque vous analysez la complexité d'un algorithme, il est généralement essentiel de définir une limite supérieure pour la rapidité avec laquelle le temps d'exécution¹ augmente lorsque la taille de l'entrée augmente. En gros, nous voulons savoir que l’exécution de l’algorithme ne prendra pas «trop longtemps». Nous ne pouvons pas exprimer cela en unités de temps réelles (secondes), car cela dépend de l'implémentation précise (la manière dont le programme est écrit, la qualité du compilateur, la rapidité du processeur de la machine,…). Nous évaluons donc ce qui ne dépend pas de ces détails, à savoir le temps nécessaire pour exécuter l'algorithme lorsque nous lui fournissons une entrée plus importante. Et nous nous soucions principalement lorsque nous pouvons être sûrs que le programme est terminé, nous voulons donc généralement savoir que cela prendra tel ou tel temps ou moins.O

Dire qu’un algorithme a un temps d’exécution de pour une taille d’entrée signifie qu’il existe une constante telle que l’algorithme se termine en au plus étapes, c’est-à-dire le temps d’exécution de l’algorithme croît au plus vite que (jusqu’à un facteur de mise à l’échelle). Notant le temps d'exécution de l'algorithme pour la taille d'entrée , signifie informellement que atteint un facteur d'échelle.O(f(n))nKKf(n)fT(n)nO(n)T(n)f(n)

Borne inférieure

Parfois, il est utile d’avoir plus d’informations qu’une limite supérieure. est l'inverse de : il exprime qu'une fonction grandit au moins aussi vite qu'une autre. signifie que pour une constante , ou pour le dire de manière informelle, up à un facteur d'échelle.ΩOT(n)=Ω(g(n))T(N)Kg(n)KT(n)g(n)

Lorsque le temps d'exécution de l'algorithme peut être déterminé avec précision, combine et : il indique que le taux de croissance d'une fonction est connu, jusqu'à un facteur de mise à l'échelle. signifie que pour certaines constantes et . De manière informelle, jusqu’à un facteur d’échelle.ΘOΩT(n)=Θ(h(n))Kh(n)T(n)Kh(n)KKT(n)h(n)

Autres considérations

Le «petit» et le sont beaucoup moins utilisés dans l'analyse de la complexité. Le petit est plus fort que le grand ; où indique une croissance qui n'est pas plus rapide, indique que la croissance est strictement plus lente. Inversement, indique une croissance strictement plus rapide.oωoOOoω

J'ai été légèrement informel dans la discussion ci-dessus. Wikipedia a des définitions formelles et une approche plus mathématique.

N'oubliez pas que l'utilisation du signe égal dans et similaires est impropre. Strictement parlant, est un ensemble de fonctions de la variable , et nous devrions écrire .T(n)=O(f(n))O(f(n))nTO(f)

Exemple: des algorithmes de tri

Comme c'est plutôt sec, laissez-moi vous donner un exemple. La plupart des algorithmes de tri ont une durée d'exécution quadratique dans le pire des cas, c'est-à-dire que pour une entrée de taille , la durée d'exécution de l'algorithme est de . Par exemple, le tri par sélection a un temps d’exécution , car la sélection du élément nécessite comparaisons, pour un total de comparaisons. En fait, le nombre de comparaisons est toujours exactement , qui croît en tant que . Nous pouvons donc être plus précis sur la complexité temporelle du tri de la sélection: c’est .nO(n2)O(n2)knkn(n1)/2n(n1)/2n2Θ(n2)

Maintenant, prenez le tri par fusion . Le type de fusion est également quadratique ( ). C'est vrai, mais pas très précis. Le tri par fusion a en fait une durée d'exécution de dans le pire des cas. Comme le tri par sélection, le flux de travail du tri par fusion est essentiellement indépendant de la forme de l'entrée et son temps d'exécution est toujours jusqu'à un facteur multiplicatif constant, c'est-à-dire .O(n2)O(nlg(n))nlg(n)Θ(nlg(n))

Ensuite, considérez quicksort . Quicksort est plus complexe. C'est certainement . De plus, le pire cas de tri rapide est quadratique: le pire est . Cependant, le meilleur cas de tri rapide (lorsque l'entrée est déjà triée) est linéaire: le meilleur que l'on puisse dire pour une limite inférieure du tri rapide en général est . Je ne répéterai pas la preuve ici, mais la complexité moyenne de quicksort (la moyenne prise sur toutes les permutations possibles de l’entrée) est .O(n2)Θ(n2)Ω(n)Θ(nlg(n))

Il existe des résultats généraux sur la complexité des algorithmes de tri dans les paramètres courants. Supposons qu'un algorithme de tri ne puisse comparer que deux éléments à la fois, avec un résultat oui ou non ( ou ). Ensuite, il est évident que la durée d'exécution de tout algorithme de tri est toujours (où est le nombre d'éléments à trier), car l'algorithme doit comparer chaque élément au moins une fois pour savoir où il se placera. Cette limite inférieure peut être satisfaite, par exemple, si l'entrée est déjà triée et que l'algorithme compare simplement chaque élément au suivant et les maintient dans l'ordre (c'est-à comparaisons). Ce qui est moins évident, c’est que la durée maximale est nécessairementxyx>yΩ(n)nn1Ω(nlg(n)) . Il est possible que l'algorithme fasse parfois moins de comparaisons, mais il doit exister une constante telle que pour toute taille d'entrée , il existe au moins une entrée pour laquelle l'algorithme fait plus que comparaisons. L'idée de la preuve est de construire l'arbre de décision de l'algorithme, c'est-à-dire de suivre les décisions que l'algorithme prend à partir du résultat de chaque comparaison. Comme chaque comparaison renvoie un résultat oui ou non, l’arbre de décision est un arbre binaire. Il y en apermutations possibles de l’entrée, et l’algorithme doit faire la distinction entre elles, la taille de l’arbre de décision est doncKnKnlg(n)n!n!. Comme l’arbre est un arbre binaire, il faut une profondeur de pour s’adapter à tous ces nœuds. La profondeur correspond au nombre maximal de décisions prises par l'algorithme. Son exécution implique donc au moins ce nombre de comparaisons: le temps d'exécution maximal est .Θ(lg(n!))=Θ(nlg(n))Ω(nlg(n))

¹ Ou d’autres ressources, telles que l’espace mémoire. Dans cette réponse, je ne considère que le temps en cours.

Gilles
la source
1
"Cependant, le meilleur cas de tri rapide (lorsque l'entrée est déjà triée) est linéaire", c'est le pire des cas !!
user5507
@ user5507: En fait, cela dépend de la stratégie de pivot. Si le premier (ou le dernier) élément est choisi comme pivot, vous avez raison; mais si vous choisissez l'élément du milieu ou la médiane des entrées première, moyenne, dernière, puis triées, c'est le meilleur des cas.
Chirlu
"Les petits o et ω sont utilisés beaucoup moins souvent dans l'analyse de complexité." Ce n'est pas vrai dans l'analyse de la complexité de l'espace. Dans l'analyse de la complexité temporelle, vous utilisez généralement o et ω lorsque vous comptez des opérations spécifiques (comparaisons, recherches de disque, erreurs de cache, etc.). Mais comme vous pouvez toujours attendre et acheter un ordinateur plus rapide, le "temps passé sur le mur" correspond toujours "à un facteur constant", de sorte que big-O est bien plus courant. Dans l’analyse de l’espace, il existe souvent des bornes inférieures dures à cause de la théorie de l’information. Il est donc extrêmement courant de voir la taille indiquée comme "f (n) + o (f (n)) bits" où f (n) est la limite inférieure.
Pseudonyme le
Alors que j'y pense: Si f (n) est une limite inférieure théorique sur la taille de certaines structures de données, celle qui utilise f (n) + O (1) (surcharge constante) est appelée "implicite", celle qui utilise f (n) + O (f (n)) (surcoût relatif constant) est appelé "compact", et celui qui utilise f (n) + o (f (n)) (le surcoût relatif devient finalement insignifiant) est appelé "succinct ". De bonnes conditions pour savoir si vous devez travailler dans cet espace.
Pseudonyme le
17

Typiquement, est utilisé pour indiquer les limites supérieures (une estimation en partant du haut), tandis que est utilisé pour énoncer des limites inférieures (une estimation en partant du dessous), et est utilisé quand ils correspondent, auquel cas vous pouvez utiliser à leur place (généralement) pour énoncer le résultat.OΩΘΘ

Kaveh
la source
3
"Typiquement"? Ils peuvent être utilisés pour autre chose?
svick
1
@svick, oui, par exemple qui n'est pas une instruction de limite supérieure. Par déclaration supérieure, j'entends quelque chose comme qui exprime une limite supérieure sur . f = O ( g ) fP=DTime(nO(1))f=O(g)f
Kaveh
4
P=DTime(nO(1))P=DTime(nΘ(1))
@JeffE, je le considère comme une égalité entre des ensembles de fonctions, mais vous avez raison, vous pouvez également le considérer comme une limite supérieure dans un sens plus général.
Kaveh
PDTIME(nΘ(1))DTIME(Θ(nlogn))PDTIME(Θ(nlogn))DTIME(nΘ(1))=