Je n'arrive pas à comprendre comment identifier une fonction avec un temps logarithmique.
Les attributs les plus courants de la fonction de temps de fonctionnement logarithmique sont les suivants :
- le choix de l'élément suivant sur lequel effectuer une action est une possibilité parmi d'autres, et
- un seul devra être choisi.
o
- les éléments sur lesquels l'action est effectuée sont des chiffres de n
C'est pourquoi, par exemple, la recherche de personnes dans un annuaire téléphonique est O(log n). Vous n'avez pas besoin de vérifier chaque Au lieu de cela, vous pouvez simplement diviser et conquérir en cherchant en fonction de la position alphabétique de leur nom, et dans chaque section, vous n'avez besoin d'explorer qu'un sous-ensemble de chaque section avant de trouver le numéro de téléphone de quelqu'un.
Bien sûr, un annuaire plus grand vous prendra toujours plus de temps, mais il n'augmentera pas aussi rapidement que l'augmentation proportionnelle de la taille supplémentaire.
Nous pouvons étendre l'exemple de l'annuaire téléphonique pour comparer d'autres types d'opérations et de services. leur temps de fonctionnement. Nous supposerons que notre annuaire téléphonique a entreprises (les "Pages Jaunes") qui ont des noms et des noms uniques personnes (les "pages blanches") qui peuvent ne pas avoir de nom unique. Un numéro de téléphone est attribué à une seule personne ou entreprise au maximum. Nous supposerons également qu'il faut un temps constant pour passer à une page spécifique.
Voici les temps d'exécution de certaines opérations que nous pourrions effectuer sur l'annuaire téléphonique, du plus rapide au plus lent :
-
O(1) (dans le pire des cas) : En fonction de la page sur laquelle figure le nom d'une entreprise et du nom de l'entreprise, trouvez le numéro de téléphone.
-
O(1) (dans le cas moyen) : Étant donné la page sur laquelle se trouve le nom d'une personne et son nom, trouvez le numéro de téléphone.
-
O(log n) : Pour trouver le numéro de téléphone d'une personne, choisissez un point au hasard à peu près au milieu de la partie du livre que vous n'avez pas encore fouillée, puis vérifiez si le nom de la personne se trouve à ce point. Répétez ensuite le processus à peu près au milieu de la partie du livre où se trouve le nom de la personne. (Il s'agit d'une recherche binaire du nom d'une personne).
-
O(n) : Trouvez toutes les personnes dont le numéro de téléphone contient le chiffre "5".
-
O(n) : Si l'on vous donne un numéro de téléphone, trouvez la personne ou l'entreprise qui a ce numéro.
-
O(n log n) : Il y a eu une confusion chez l'imprimeur, et toutes les pages de notre annuaire téléphonique ont été insérées dans un ordre aléatoire. Corrigez l'ordre en regardant le premier nom sur chaque page et en plaçant cette page à l'endroit approprié dans un nouvel annuaire vide.
Pour les exemples ci-dessous, nous nous trouvons maintenant chez l'imprimeur. Des annuaires téléphoniques attendent d'être envoyés à chaque personne ou entreprise, et un autocollant sur chaque annuaire indique à qui il doit être envoyé. Chaque personne ou entreprise reçoit un annuaire.
-
O(n log n) : Nous voulons personnaliser l'annuaire téléphonique, donc nous allons trouver le nom de chaque personne ou entreprise dans son exemplaire désigné, puis entourer son nom dans l'annuaire et écrire une courte note de remerciement pour son parrainage.
-
O(n 2 ) : Une erreur s'est produite au bureau, et chaque entrée dans chacun des annuaires téléphoniques a un "0" supplémentaire à la fin du numéro de téléphone. Prenez du white-out et effacez chaque zéro.
-
O(n - n !): Nous sommes prêts à charger les annuaires téléphoniques sur le quai d'expédition. Malheureusement, le robot qui était censé charger les livres s'est détraqué : il place les livres dans le camion dans un ordre aléatoire ! Pire encore, il charge tous les livres sur le camion, puis vérifie s'ils sont dans le bon ordre, et sinon, il les décharge et recommence. (C'est le redoutable triage par bogo .)
-
O(n n ) : Tu répares le robot pour qu'il charge les choses correctement. Le lendemain, un de vos collègues vous fait une farce et connecte le robot du quai de chargement aux systèmes d'impression automatisés. Chaque fois que le robot va charger un annuaire original, l'imprimante de l'usine fait un tirage en double de tous les annuaires ! Heureusement, les systèmes de détection de bugs du robot sont suffisamment sophistiqués pour que le robot n'essaie pas d'imprimer encore plus de copies lorsqu'il rencontre un livre en double à charger, mais il doit quand même charger tous les livres originaux et en double qui ont été imprimés.
82 votes
Un arbre binaire à 1 nœud a une hauteur de log2(1)+1 = 1, un arbre à 2 nœuds a une hauteur de log2(2)+1 = 2, un arbre à 4 nœuds a une hauteur de log2(4)+1 = 3, et ainsi de suite. Un arbre à n nœuds a une hauteur log2(n)+1, de sorte que l'ajout de nœuds à l'arbre entraîne une croissance logarithmique de sa hauteur moyenne.
44 votes
Une chose que je vois dans la plupart des réponses est qu'elles décrivent essentiellement "O(quelque chose)" signifie que le temps d'exécution de l'algorithme croît proportionnellement à "quelque chose". Étant donné que vous avez demandé la "signification exacte" de "O(log n)", ce n'est pas vrai. C'est la description intuitive de la notation Big-Theta, pas Big-O. O(log n) signifie intuitivement que le temps d'exécution augmente au maximum proportionnel à "log n" : stackoverflow.com/questions/471199/
3 votes
Related stackoverflow.com/questions/487258/
42 votes
Je me souviens toujours de diviser pour régner comme l'exemple de O(log n).
2 votes
Tromperie sur votre fonction : Elle est linéaire par rapport à la VALEUR de l'entrée, cependant - si nous considérons n comme un vecteur de bits (comment nous représentons l'entrée) - elle est en fait O(2^n) en termes de TAILLE de l'entrée (c'est-à-dire qu'il faut lg(n) bits pour représenter n, donc si n a une longueur de k bits, la boucle itère jusqu'à 2^k fois). Je dirais donc que la boucle est exponentielle, et non linéaire.
28 votes
Il est important de réaliser que son logarithme est en base 2 (et non en base 10). En effet, à chaque étape d'un algorithme, vous supprimez la moitié des choix restants. En informatique, nous utilisons presque toujours le logarithme en base 2 car nous pouvons ignorer les constantes. Il existe toutefois quelques exceptions (par exemple, les temps d'exécution de l'arbre quadruple sont en log base 4).
19 votes
@Ethan : Cela n'a pas d'importance dans quelle base vous êtes, puisque la conversion de base est juste une multiplication constante, La formule est log_b(x) = log_d(x) / log_d(b). Log_d(b) sera juste une constante.
5 votes
Quelques informations de base sur les logarithmes ! 1. Démystifier le logarithme naturel 2. Utilisation des logarithmes dans le monde réel
2 votes
@mdkess Oui je sais que c'est un facteur constant, je l'ai même dit dans mon commentaire. Je soulignais que les temps d'exécution logarithmiques impliquent souvent de diviser vos choix en deux, contrairement à un temps d'exécution logarithmique en base 10 qui impliquerait de supprimer 9/10e de vos choix à chaque étape. Je faisais donc remarquer au PO que nous nous retrouvons souvent à diviser nos choix en deux à chaque étape d'un algorithme, ce qui donne un temps d'exécution logarithmique de base 2 et non logarithmique de base 10. Réaliser cela est utile pour pouvoir regarder un code et dire "Oh, c'est O(logn)". Je ne parlais pas vraiment de temps d'exécution réel.
3 votes
@Ethan : Vous êtes toujours incorrect. Si quelque chose est O(log_b(n)), b > 1, c'est O(log_c(n)) pour tout c > 1. Donc, en divisant vos choix en deux, vous obtenez un temps O(log_2(n)) ET un temps O(log_10(n)) ET un temps d'exécution O(log_12838(n)). Cela n'a pas d'importance. La conversion de la base logarithmique est une multiplication constante, qui est dominée par la fonction logarithme - c'est-à-dire que O(c*f(n)) est O(f(n)) si c est une constante.
2 votes
@mdkess Je ne cherche pas la rigueur algorithmique, j'essaie juste de créer une correspondance mentale entre quelque chose dans le code et quelque chose étant O(logn). Bien sûr, à ce jour, toute tentative d'y parvenir a été détruite. Super. Et pour l'enregistrement, je n'ai pas tort car j'ai dit que le temps d'exécution était log base 10, je n'ai pas fait référence à la notation big O. Donc si vous voulez être formel, ce serait T(log base 10 (n)). Maintenant, si vous voulez arrêter de discuter de sémantique, ce serait génial.
1 votes
@Ethan : En supposant que par T vous voulez dire big-Theta, alors vous avez raison - mais c'est aussi T(log base 43 (n)) et T(log base 378 (n)), par définition.
3 votes
@mdkess Je ne veux pas dire grand Thêta. T_n est la fonction qui représente le temps d'exécution exact du code. Par exemple : T_n = 5 + 8n + n^2. Le grand O de T_n est O(n^2).
2 votes
Quelqu'un peut-il dire à quoi correspond le O ? Sortie ?
1 votes
@clankill3r programmateurs.stackexchange.com/a/107977/8613
1 votes
J'ai récemment regardé une vidéo qui décrit parfaitement Log N. Il faut absolument la regarder. youtube.com/watch?v=kjDR1NBB9MU
2 votes
Peut-être serait-il utile svitlanamoiseyenko.com/2016/08/30/olog-n-et-combien-c'est-rapide