Cette question concerne l'algorithme de Fisher-Yates pour renvoyer un mélange aléatoire d'un tableau donné. La page Wikipedia dit que sa complexité est O (n), mais je pense que c'est O (n log n).
Dans chaque itération i, un entier aléatoire est choisi entre 1 et i. La simple écriture de l'entier en mémoire est O (log i), et comme il y a n itérations, le total est
O (log 1) + O (log 2) + ... + O (log n) = O (n log n)
ce qui n'est pas mieux l'algorithme naïf. Est-ce que j'ai râté quelque chose?
Remarque: L'algorithme naïf consiste à attribuer à chaque élément un nombre aléatoire dans l'intervalle (0,1), puis à trier le tableau en fonction des nombres attribués.
la source
Le modèle standard de calcul suppose que les opérations arithmétiques sur des entiers O (log n) bits peuvent être exécutées en temps constant, car ces opérations sont généralement remises au matériel. Ainsi, dans l'algorithme de Fisher-Yates, «écrire l'entier i en mémoire» ne prend que O (1).
Bien sûr, il est parfaitement significatif d'analyser l'algorithme en termes d'opérations sur les bits, mais le modèle de coût en bits est moins prédictif du comportement réel. Même la boucle simple
for i = 1 to n: print(i)
nécessite des opérations sur O (n log n) bits.la source
Ceci est une réponse à "[l'algorithme de Fisher-Yates] n'est pas meilleur que l'algorithme naïf. Suis-je en train de manquer quelque chose ici?" que vous avez posé dans la question.
Dans votre algorithme "naïf" qui utilise des nombres réels: combien de bits de précision utilisez-vous? Si vous comptez la complexité des bits (comme vous semblez le faire pour Fisher-Yates), et que l'algorithme utilise k bits aléatoires pour les nombres réels, alors son temps d'exécution serait Ω (kn log n), car en comparant deux k- les nombres réels binaires prennent du temps Ω (k). Mais k doit être d'au moins Ω (log n) pour éviter que deux éléments soient mappés au même nombre réel, ce qui signifie que l'algorithme prend du temps Ω (n log 2 n), ce qui est plus lent que le shuffle de Fisher-Yates par un facteur de log n.
Si vous comptez simplement le nombre d'opérations arithmétiques et de comparaison et ignorez leur complexité en bits, alors Fisher-Yates est Θ (n) et votre algorithme est Θ (n log n), toujours un facteur de log n à part.
la source
Les entiers n'ont rien de spécial pour ce problème.
Par exemple, les tables de hachage (stockant tout type de valeurs) ne sont pas O (1) temps d'accès si la fonction de hachage doit lire la valeur entière pour calculer son hachage. n éléments uniques ont besoin de log n bits chacun en moyenne pour représenter, quelle que soit l'intelligence de votre représentation, et toute fonction de hachage qui lit toute son entrée prendra donc au moins autant de temps à calculer. En pratique, ils sont plus rapides que les arbres rouge-noir, mais asymptotiquement ils ne sont pas meilleurs.
Le brouhaha référencé par randomwalker concernait un article POPL 2008 ( http://portal.acm.org/citation.cfm?doid=1328438.1328460 ), discuté ici: http://blog.computationalcomplexity.org/2009/05/shaving- logs-with-unit-cost.html
Dans ce post, Lance Fortnow décrit comment en tant qu'étudiant, il s'est plaint que le tri nécessite vraiment n log ^ 2 n temps si nous devons lire tous les log n bits de deux éléments afin de les comparer, ce qui semble une objection raisonnable.
la source
En fait, O (n log n) est une borne inférieure pour ce problème dans les modèles où le tri est O (n log n). Si toutes les permutations sont également probables, l'algorithme en fonction des flux aléatoires aux permutations doit être surjectif. Il y en a n! permutations donc dans quelque chose comme un modèle d'arbre de décision, il y a des branches de longueur au moins O (log n!) = O (n log n).
la source
Dans TCS, nous considérons - sauf indication contraire explicite - la complexité d'une machine de Turing. Bien que cela soit correct à des fins théoriques, les résultats ne sont pas très utiles dans la pratique car nous implémentons différents modèles de machine (c'est-à-dire des approximations finies) dans le matériel. Il est donc possible de demander la complexité de ces modèles. Par exemple, nous supposons généralement que les machines à registres (similaires aux CPU réels) peuvent effectuer des opérations atomiques sur deux registres en temps constant - c'est ce qui aurait pu être utilisé ici.
En bref: vous pensez en termes de MT, les auteurs de l'article en termes de RM. Vous avez tous les deux raison.
la source