Comment faire pivoter un tableau d'entiers de i
fois en utilisant la fonction swap
uniquement en temps linéaire.Algorithme de rotation d'une matrice en temps linéaire
Répondre
Vous pouvez le faire dans le temps linéaire en utilisant un assistant inverse().
// rotate array of size=size, by n positions
void rotate(int array[], int size, int n)
{
// reverse array[0...size-1]
reverse(array, 0, size-1);
// reverse A[0...n-1]
reverse(array, 0, n-1);
// reverse A[n...size-1]
reverse(array, n, size-1);
}
// reverse elements in the array[pos_from ... pos_to]
void reverse(int array[], int pos_from, int pos_to)
{
...
}
La mise en œuvre au moyen de swaps reverse(int array[], int pos_from, int pos_to)
est laissé comme un exercice pour le lecteur. Astuce: Cela peut être fait en temps linéaire.
Je suis juste curieux de savoir pourquoi ça marche tout le temps – daydreamer
@daydreamer Vous pouvez vous référer à ce document: http://www.cs.bell-labs.com/cm/cs/pearls/s02b.pdf Si vous échangez le 2ème et 3e inverse dans le code de Sanjit, c'est plus facile à comprendre. –
Le lien ne fonctionne pas. Pouvez-vous fournir un lien avec une preuve pour cette méthode? – Daggerhunt
une naïve mise en œuvre de pseudocode:
for (n = 0; n < i; n++) {
for (j = array.length-1; j > n; j--)
swap(j, j-1)
}
se déplace à plusieurs reprises le dernier élément à l'avant, l'arrêt avant de se déplacer quoi que ce soit déplacé auparavant à l'avant
J'ai essayé même soln mais je le veux dans o (n) –
@prp - Peut-être mentionné dans la question alors, hein? –
pourquoi seule fonction d'échange?
O (n) dans le temps et l'espace:
var rotateCount = 1;
var arr = new Array(1,2,3,4,5,6,7,8,9,10);
tmp = new Array(arr.length);
for (var i = 0; i<arr.length; i++)
tmp[(i+rotateCount)%arr.length]=arr[i];
arr = tmp;
alert(arr);
Disons que nous avons une fonction appelée arr_reverse(arr,i,j)
qui inverse les éléments du tableau arr
entre l'indice i
et j
en utilisant la fonction swap
.
Exemple:
arr = {1,2,3,4,5}
i = 0
j = 2
alors la fonction retournera:
{3,2,1,4,5}
^^^^^
La mise en œuvre de cette fonction est simple et est O(N)
.
Utilisons maintenant cette fonction pour faire pivoter la matrice.
arr = {1,2,3,4,5} // input array
k = 2 // amount of right rotation
result = {4,5,1,2,3} // expected result
l = 5 // length of array.
Step 1: Call arr_reverse(arr,l-k,l-1) which is arr_reverse(arr,3,4)
we get {1,2,3,5,4}
^^^
Step 2: Call arr_reverse(arr,0,l-k-1) which is arr_reverse(arr,0,2)
we get {3,2,1,5,4}
^^^^^
Step 3: Call arr_reverse(arr,0,l-1) which is arr_reverse(arr,0,4)
we get {4,5,1,2,3}
^^^^^^^^^
L'ensemble du processus utilise arr_reverse
3 fois, ce qui en fait O(N)
Mieux utiliser une fonction directe et simple, la complexité N:
int rotate(int* a,int DIM,int rn,int* b) {
int i; //counter
for(i=0;i<DIM;i++){ // looping through the array
b[(i+rn)%len]=a[i]; // copying the values in the b array=a shifted with rn(+ for right or - for left shifting
}
En utilisant O temps linéaire (2N + m), et l'espace constant O (4). m = GCD (n, p)
Il est jusqu'à 50% plus rapide que l'approche de permutation, car l'échange nécessite d'écrire O (N) fois à un moment.
http://www.eis.mdx.ac.uk/staffpages/r_bornat/oldteaching/I2A/slides%209%20circshift.pdf
for (m=0, count=0; count!=n; m++) {
type t=A[m];
for (i=m, j=m+p; j!=m; i=j, j = j+p<n ? j+p : j+p-n, count++)
A[i]=A[j];
A[i]=t; count++;
}
est ici une meilleure solution, d'une autre nature que les autres. Cela implique moins d'échanges de tableaux que les autres.Python:
import fractions
# rotates an array in-place i positions to the left, in linear time
def rotate(arr,i):
n = len(arr)
reps = fractions.gcd(n,i)
swaps = n/reps
for start in xrange(reps):
ix = start
tmp = arr[ix]
for s in xrange(swaps-1):
previx = ix
ix = (ix + i) % n
arr[previx] = arr[ix]
arr[ix] = tmp
return arr
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package rotateinlineartime;
/**
*
* @author Sunshine
*/
public class Rotator {
void reverse(int a[], int n) {
for (int i = 0; i <= n - 1; i++) {
int temp;
temp = a[i];
a[i] = a[n - 1];
a[n - 1] = temp;
n--;
}
printArray(a);
}
void printArray(int a[]) {
for (int i = 0; i < a.length; i++) {
System.out.println(a[i]);
}
}
}
/* Q: How can we shift/rotate an array in place?
A: "in place" means O(1) space complexity, so we need to do some trick
*/
#include <iostream>
#include <algorithm>
using namespace std;
void ArrayRotate(int a[], int n, int k)
{
if (n < 1 || k % n == 0) return;
k %= n;
if (k < 0) k += n;
reverse(a, a+k);
reverse(a+k, a+n);
reverse(a, a+n);
}
void PrintArray(int a[], int n)
{
for (int i = 0 ; i < n; ++i)
cout << a[i] << " ";
cout << endl;
}
int main()
{
int a[] = { 1, 2 , 3, 4, 5 };
int n = sizeof(a)/sizeof (a[0]);
PrintArray(a, n);
ArrayRotate(a, n, 2);
PrintArray(a, n);
return 0;
}
/* Output:
1 2 3 4 5
3 4 5 1 2
*/
l'aide de swaps seulement, suivant est un implémentation C++
template<class T>
void rotate_array(std::vector<T> *array, int i) {
int n = array->size();
i = i % n;
int gcd_n_i = gcd(i, n);
for (int j = 0; j < gcd_n_i; j++) {
T first_element = array->at(j);
for (int k = j; (k + i) % n != j; k = (k + i) % n) {
std::swap(array->at(k), array->at((k + i) % n));
}
}
}
Vous pouvez en lire davantage à http://pointer-overloading.blogspot.in/2013/09/algorithms-rotating-one-dimensional.html
void reverse_array(int a[], int start, int end){
while(start < end){
int temp = a[start];
a[start] = a[end];
a[end] = temp;
start++;
end--;
}
}
void rotate_array(int a[], int pivot, int len){
int i;
/*Reverse the whole array */
reverse_array(a, 0, len);
/* Reverse from 0 to pivot and pivot to end */
reverse_array(a,0, pivot);
reverse_array(a,pivot+1,len);
}
Veuillez développer votre question un peu. Quelle dimension a le tableau? Que voulez-vous dire par "rotation d'un tableau"? Donnez un exemple d'entrée et de sortie. Pensez à utiliser des signes de ponctuation et des majuscules, le cas échéant. –
Qu'avez-vous essayé? Comment ça ne marche pas? IOW, vous devez essayer d'abord avant de vous aider (nous n'allons pas l'écrire à partir de vous) – KevinDTimm
@sven supposons que le tableau d'entrée est le tableau de sortie {1,2,3,4,5} après qu'une rotation à droite est {5, 1,2,3,4}. –