Complexité de l'application d'une permutation sur place

27

À ma grande surprise, je n'ai pas pu trouver de documents à ce sujet - probablement recherché les mauvais mots clés.

Donc, nous avons un tableau de tout, et une fonction sur ses indices; f est une permutation.ff

Comment réorganiser le tableau selon avec une mémoire et une exécution aussi proches que possible de O ( 1 ) et O ( n ) ?fO(1)O(n)

Y a-t-il des conditions supplémentaires lorsque cette tâche devient plus facile? Par exemple, lorsque nous savons explicitement qu'une fonction est l'inverse de f ?gf

Je connais un algorithme qui suit les cycles et parcourt un cycle pour chaque index pour vérifier s'il est le moins dans son cycle, mais encore une fois, il a le pire cas d' exécution , bien qu'en moyenne il semble se comporter mieux. ..O(n2)

jkff
la source
Une observation facile: si non seulement le tableau des éléments mais aussi le tableau contenant la fonction f est accessible en écriture, il est facile d'effectuer la tâche en temps O (n) en utilisant des registres entiers O (1) (chacun de longueur O ( log n) bits) et de l'espace supplémentaire pour un élément en suivant simplement chaque cycle. Mais cela ne fonctionne pas si la fonction f est donnée sur un stockage en lecture seule (ou f n'est donnée que comme un oracle), ce qui, je pense, est une hypothèse dans cette question.
Tsuyoshi Ito
23
Fich et al. 1995 : temps, O ( log n ) espace. Il aborde également certains cas particuliers. O(nlogn)O(logn)
Jukka Suomela
Oui, je suppose que nous avons f comme oracle.
jkff
3
@JukkaSuomela, vous devriez en faire une réponse. De plus, étant donné que est une permutation arbitraire, un simple argument d'entropie donne O ( n log n ) espace et / ou temps, donc je serais surpris si vous pouviez faire mieux que O ( n log n ) dans le temps et l' espace. fO(nlogn)O(nlogn)
user834

Réponses:

4

O(nlogn)O(log2n)

Option 1: trichez en compressant votre permutation en une structure de données succincte, voir Munro http://www.itu.dk/people/ssrao/icalp03-a.pdf .

Option 2: utilisez une décomposition de cycle primaire pour stocker la perm succinctement et utilisez cet espace supplémentaire pour tricher http://oeis.org/A186202

O(n2)O(#cycleslogn)

O(n2distinct_cycle_lengths)O((#cycles_with_same_size)logn)

i=1..np(i)iO(n2)O(logn)

Chad Brewbaker
la source
nlogn
# 5 utilise moins d'espace que # 0 par un facteur log (n).
Chad Brewbaker
1

Si vous utilisez la représentation du cycle de la permutation, vous avez besoin d'un élément de tableau supplémentaire pour stocker l'élément en cours de permutation et vous pouvez parcourir les cycles dans au pire les opérations O (N).

Phil
la source
2
jkff a déjà dit qu'il connaissait l'algorithme de suivi de cycle, donc il veut clairement que la permutation elle-même soit traitée comme (proche) d'une boîte noire. Comme il le fait remarquer dans la question, la conversion d'une boîte (presque) noire en représentation cyclique peut prendre du temps O (n ^ 2).
Joshua Grochow
La boîte noire p (i) est très bien. Vous faites simplement le tour du cycle jusqu'à ce que vous reveniez à i. Le problème est lié à la complexité de Kolomogorov pour stocker la liste des éléments qui ont été mis à jour afin de ne pas les répéter plusieurs fois. Munro a des limites à cela. itu.dk/people/ssrao/icalp03-a.pdf
Chad Brewbaker
-2

Toute permutation de N éléments peut être convertie en toute autre permutation en utilisant N-1 ou moins d'échanges. Le pire des cas pour cette méthode peut nécessiter des appels O (n ^ 2) vers votre oracle, F (). Commencez par la moindre position. Soit x la position que nous échangeons actuellement.

Si F (x)> = x, permutez les positions x et F (x). Sinon, nous devons trouver où l'élément qui était en position F (x) est actuellement dans la liste. Nous pouvons le faire avec l'itération suivante. Soit y = F (x). Faire jusqu'à y> = x: y = F (y): Fin Do. Échangez maintenant les positions x et y.

Russell Easterly
la source
3
O(n2)
Désolé. Je suis nouveau dans ce groupe. J'aime cette méthode en raison de sa simplicité. Je trouve parfois la simplicité plus rapide que l'efficacité. Je connais une autre méthode qui nécessite O (n) étapes, mais l'espace O (nlogn).
Russell Easterly
1
Russell, même allouer et mettre à zéro l'espace O (n log n) est déjà O (n log n), vouliez-vous dire dans l'autre sens?
jkff
Vous n'avez pas vraiment d'allocation et d'espace zéro. L'idée de base est lorsque F (x)> x, nous devons nous rappeler où nous mettons l'élément à la position x. Pour un très grand n, j'utiliserais une base de données et garderais simplement un enregistrement de l'endroit où l'élément x est déplacé. L'enregistrement peut être supprimé lorsque x arrive à son emplacement final.
Russell Easterly
1
Mais pourquoi dites-vous alors qu'il nécessite un espace O (n log n)?
jkff
-2

Cette méthode utilise l'inverse de F et nécessite n bits de stockage. Si x est la position d'un élément dans le tableau d'origine, soit G (x) la position de l'élément dans le tableau trié. Soit B un tableau de n bits. Réglez tous les n bits de B sur 0.

POUR x = 1 à n-1: SI B (x) == 0 ALORS: y = G (x): FAIRE JUSQU'À x == y: Inverser les positions x et y: B (y) = 1: y = G ( y): BOUCLE: ENDIF: SUIVANT X

Cette méthode continue de permuter l'élément actuellement en position x à la position finale de l'élément. La boucle intérieure se termine lorsque l'élément correct est échangé en position x. Étant donné que chaque échange déplace au moins un élément vers sa position finale, la boucle intérieure Do ne peut pas s'excuser plus de n-1 fois pendant l'exécution. Je pense que cette méthode est O (n) temps et espace.

Russell Easterly
la source
2
Avez-vous regardé le papier? Les deux algorithmes que vous listez ici sont les deux "évidents". Le papier en présente des moins évidents avec des compromis spatio-temporels différents, en particulier beaucoup moins d'espace.
Yuval Filmus