circulaire de décalage vers la gauche d'un tableau de n positions en java
Je suis en train de faire la circulaire de décalage vers la gauche d'un tableau de n positions à l'aide d'un seul tableau 1D. Je peux le faire dans les deux tableaux, mais je n'ai pas compris comment le faire en utilisant un. Veuillez donner vos suggestions
- Qu'avez-vous essayé?
- c'est ce que j'ai essayé
Collections.rotate(Arrays.asList(array), distance)
- double possible de le plus Rapide de l'algorithme de cercle maj N tableau de taille pour la position M
Vous devez vous connecter pour publier un commentaire.
Il est en fait un algorithme intelligent pour cela. Nous allons utiliser
A
pour désigner la matrice,N
pour désigner la taille de la matrice, etn
pour indiquer le nombre de postes à changement. Après le changement que vous souhaitez lei-th
élément à déplacer à la((i + n) mode N)-th
position, par conséquent, nous pouvons définir les postes par le mappage suivant:L'idée générale derrière cet algorithme va comme ceci: Nous ne voulons pas de déplacer les éléments autour de plus nécessaire, de sorte que, idéalement, nous aimerions tout simplement de placer chaque élément dans c'est bon (déplacé) position sur le premier essai. Dites-nous commencer avec l'élément à la position
i
. Ce que nous voulons faire est de déplacer l'élément à la positioni
positionf(i)
, mais ensuite, nous allons remplacer l'élément à cette position, nous devons d'abord enregistrer l'élément à la positionf(i)
et ensuite effectuer la maj. Une fois que nous avons changé le premier élément, nous avons besoin de choisir un autre élément à déplacer. Puisque nous voulons économiser de l'espace, le candidat est l'élément que nous venez d'enregistrer (l'élément qui était en positionf(i)
). Comme avant, nous économisons de l'élément à la positionf(f(i))
puis copier nos enregistré élément dans cette position. Nous continuons à répéter ce processus (en passant par des postes dei, f(i), f(f(i)), f(f(f(i))), ...
) jusqu'à ce que nous atteignons un élément que nous avons déjà décalé (qui nous sont gauranteed à faire, car il y a finitly beaucoup de position). Si nous avons passé en revue tous les éléments, alors nous sommes fait, si non, alors nous avons sélectionner un autre élément (qui n'a pas été déplacé encore), dire à la positionj
, et répétez la procédure (en passant parj, f(j), f(f(j)), f(f(f(j))), ...
). C'est tout. Mais avant que nous puissions mettre en œuvre un tel algorithme, ou même avant de nous décider si c'est en effet un bon algorithme, nous avons besoin de répondre à quelques questions:Dire que nous parcourir les positions
i, f(i), f(f(i)), ...
. Comment pouvons-nous dire que nous avons atteint une position qui a déjà été changé? Devons-nous sauver tous les postes que nous avons passé à travers? Si nous le faisons, alors cela signifie que nous devons tenir un tableau de taille N (pour couvrir toutes les positions), et nous avons aussi besoin pour effectuer une recherche à chaque fois que l'on passe d'un élément. ce serait faire l'algorithme terriblement innefficient. Heureusement, ce n'est pas nécessaire, puisque la séquencei, f(i), f(f(i)), ...
devez enrouler autour de lui-même à la positioni
, donc nous avons seulement besoin d'attendre jusqu'à ce que nous arrivons à la position. Nous pouvons le prouver, ce qui assetion comme suit: Supposons que le premier élément répété que nous rencontrons n'est pasi
. Nous devons alors avoir 2 différents éléments, que lorsqu'il est décalé arriverez à la même position - une contradiction.Dire que nous avons fini en passant par
i, f(i), f(f(i)), ...
, mais il y a encore des éléments qui restent unshifted (on peut dire par le calcul du nombre d'éléments nous avons changé). Comment faisons-nous maintenant à trouver une positionj
qui contient un tel élément? Et aussi, une fois que nous avons terminé cette deuxième itération (en passant parj, f(j), f(f(j)), ...
) comment pouvons-nous trouver un troisième positionk
avec un unshifted élément? et ainsi de suite.. Cela aussi, nous devons enregistrer un tableau de compte pour utilisé\les éléments non utilisés, et perfrom une recherche à chaque fois que nous avons besoin de trouver un élément non utilisé. Toutefois, nous pouvons à nouveau se détendre, car, comme nous allons le découvrir bientôt, tous les positions de départ (que nous avons notée pari
,j
etk
) sont adjacentes. ce qui signifie, que si l'on commence à partir de la positioni
, nous allons ensuite sélectionneri + 1
, puisi + 2
, et ainsi de suite...les séquences
i, f(i), f(f(i)), ...
etj, f(j), f(f(j)), ...
(oùi
etj
sont différents) contiennent des éléments communs? Si ils font cela voudrait dire que l'algorithme est inutile, car il pourrait passer le meme element deux fois par l'amenant à se retrouver dans la mauvaise position. La réponse, puis (bien sûr), c'est qu'ils ne peuvent pas contenir d'éléments communs. Et nous allons voir pourquoi.Notons
d := gcd(N, n)
. Pour tous les entiers:i = 0,...,d - 1
nous définissons l'ensemble suivant:Il est facile de voir que les jeux de
S(0),...,S(d - 1)
, ensemble, couvrent l'ensemble{0,...,N - 1}
. Nous observons également que lors de la division d'un élément dans un ensembleS(i)
pard
, nous sommes laissés avec le restei
, et en divisant un élément d'un autre ensembleS(j)
pard
va nous laisser avec un autre reste (j
). Ainsi, deux ensembles contiennent un élément commun. Avec cela, nous avons établi que les jeux deS(0),...,S(d - 1)
forment une partition de{0,...,N - 1}
Maintenant, pour chaque
i = 0,...,d - 1
, nous allons définir l'ensembleT(i)
commei, f(i), f(f(i)), ...
. Par la définition def
nous pouvons écrireT(i)
comme suit:Nous observons que si
x
est un élément de laT(i)
, alors on peut écrire pour certainsk
:Notons
z := k(n/d) mod N/d
, puis en multipliant pard
, nous avons:et donc:
Ainsi,
x
est aussi dansS(i)
. De même, Si l'on prend lay
deS(i)
nous observons que, pour certainsk
:Depuis
gcd(n/d, N/d) = 1
il existe unq
tels queq(n/d) mod N/d = 1
(modulaire inverse), donc on peut écrire (en multipliant parkd
):et donc:
Ainsi,
y
est aussi dansT(i)
. Nous concluons queT(i) = S(i)
. De ce fait, nous pouvons facilement montrer notre précédente assetions. Tout d'abord, depuis les ensembles forment une partition de{0,...,N - 1}
la troisième assertion (pas de deux séquences contiennent un élément commun) est satisfaite. Deuxièmement, par la définition des ensembles deS(i)
nous pouvons prendre n'importe quel groupe ded
les éléments adjacents dans{0,...N - 1}
et chacun d'eux sera placé dans un autre ensemble. Cela répond à la seconde affirmation.Ce que cela signifie est que l'on peut faire tourner tous les éléments dans des positions
0, d, 2d, ..., (N/d - 1)d
par le simple remplacement de l'élément à la positionn mod N
avec l'élément à la position0
, l'élément à la position2n mod N
avec l'élément à la positionn mod N
, et ainsi de suite ... jusqu'à notre retour à l'élément en position0
(qui nous sont assurés qui va arriver). Voici un pseudo-code exemple:Ce couvre l'ensemble
S(0)
. Pour couvrir le reste des séries, à SavoirS(1), ... ,S(d-1)
, il vous suffit de faire une itération sur chaque jeu de la même manière que nous avons fait pour la première:Note que bien que nous avons deux boucles imbriquées, chaque élément est déplacé exactement une fois, et nous utilisons
O(1)
de l'espace. Un exemple d'une mise en œuvre en Java:Ici est très facile de l'algorithme, avec O(1) de l'Espace en O(n)
Algorithme
Par exemple, disons que le tableau est
[1,2,3,4]
etn
est2
Après la première étape, vous vous retrouvez
[2,1,3,4]
Après Étape deux, vous vous retrouvez
[2,1,4,3]
Après Étape trois, vous vous retrouvez
[3,4,1,2]
Vous pouvez changer les données par l'itération et de la copie, ce sera en O(n). Une autre approche consiste à créer un
List
de mise en œuvre qui enveloppe votre tableau et s'expose comme étant circulaire décalé. Cela avait l'avantage que le décalage est paresseusement fait quandget
ou d'itération est effectuée.Je voudrais passer 1 élément à la fois en place, à l'aide d'une seule variable temporaire pour contenir l'élément, tout en déplaçant les éléments 1, place le long de chaque. Je ne puis répétez cette
n
fois pour obtenirn
changements.De sortie:
Pas trop inefficaces, comme
System.arraycopy()
est hautement optimisé.Une autre alternative serait d'envelopper votre propre structure, qui comprend le tableau et l'indice de zéro virtuel.
Je ne les croyons que
System.arraycopy
serait en fait il suffit de prendre l'ensemble de vos données d'un tableau et le mettre dans un autre de la même longueur juste déplacé.De toute façon de penser à ce problème est tout à fait intéressant de la tâche. La seule Solution que je pouvais penser pour le moment est de la merde un par un.
Sans l'aide d'un autre Tableau, il devrait ressembler à cela:
pour les Tableaux de plus de 30 points mais il est plus efficace d'utiliser ce:
Mais pour les grands ensembles et de grand changement qui sont proches de la taille de la matrice ainsi que pour de courts tableaux et les petites variations de cette méthode gagne la course:
J'ai testé qu'avec un peu de la taille des matrices et des changements Voici les résultats pour
en nanosecondes:
1ère méthode:5663109208
2ème méthode:4047735536
3ème méthode:6085690
Donc, vous devriez vraiment utiliser la 3ème méthode. Hope qui aide
Caisse github lien:
https://github.com/techpanja/interviewproblems/blob/master/src/arrays/circularshiftintarray/CircularShiftArray.java
circularShiftToLeftInPlace
Peut-être un vieux post.. mais voici ma solution (où
A
est évidemment le tableau etK
le nombre de postes).Java 8 version:
Comment à ce sujet?