What is a rotating array? Text + code analysis

Time:2021-7-28

The original is from WeChat official account: Jing Yu.

 

The rotation array is divided into left rotation and right rotation. The force buckle 189 is entitled right rotation, and today’s share is left rotation.

Given an array, rotate the elements in the array to the leftkLocations, wherekIs a nonnegative number.

Figure 0-1 array arr left rotation k = 2 positions

The original array is arr [] = [1,2,3,4,5,6,7]. Rotate it by 2 elements to the left to obtain the array arr [] = [3,4,5,6,7,1,2].

I recommend you to do 189 questions of force deduction and right rotation array.

Method 1 (temporary array)

This method is the most simple and intuitive. For example, when array arr [] = [1,2,3,4,5,6,7] and K = 2, the first k elements in the array are moved to the end of the array, so we only need to save the first k elements with a temporary array temp [], temp [] = [1,2], and then move the remaining elements in the array to the left by 2 positions. Arr [] = [3,4,5,6,7,6,7], Finally, save the elements in the temporary array temp back to the original array to get the rotated array arr [] = [3,4,5,6,7,1,2], as shown in Figure 1-1.

Figure 1-1 temporary array method

PS: pay attention to the boundary conditions of subscripts when writing code.

void rotationArray(int* arr, int k, int n) {
    int temp[k];    //  Temporary array
    int i,j;
    //1. Save the first k elements in array arr to temporary array temp
    for( i = 0;i < k;i++) {
        temp[i] = arr[i];
    }
    //2. Move the remaining elements in the array forward K positions
    for( i = 0;i < n-k; i++) {
        arr[i] = arr[i+k];
    }
    //3. Store the elements in the temporary array into the original array
    for( j = 0; j < k; j++) {
        arr[i++] = temp[j];
    }
}

Complexity analysis

  • Time complexity: O (n)O(n), n represents the length of the array.
  • Space complexity: \ theta (k) Θ(k), K represents the number of left-handed positions.

Method 2 (step-by-step moving method)

Step by step is to move step by step according to the definition of left rotation.

For the first rotation, save arr [0] to a temporary variable temp, then move the elements in arr [1] to arr [0], arr [2] to arr [1], and so on, and finally store temp in arr [n-1].

Similarly, taking the array arr [] = {1,2,3,4,5,6,7}, k = 2 as an example, we rotate the array twice

The array obtained after the first rotation is arr [] = {2,3,4,5,6,7,1};

The array obtained after the second rotation is arr [] = {3,4,5,6,7,1,2}.

The specific steps are shown in Figure 2-1.

Figure 2-1 step by step left-handed method

Implementation code

C language implementation

//C language implementation, learning algorithm is the important idea, and the implementation requires the basic grammar
#include
void leftRotate(int[] arr, int k, int n)
{
    int i;
    for (i = 0; i < k; i++) {
        leftRotateByOne(arr, n);
    }
}

void leftRotateByOne(int[] arr, int n) 
{
    int temp = arr[0], i;
    for (i = 0; i < n-1; i++) {
        arr[i] = arr[i+1];
    }
    arr[n-1] = temp;
}

void printArray(int arr[], int n) 
{ 
    int i; 
    for (i = 0; i < n; i++)
    {
        printf("%d ", arr[i]);         
    }
}

int main()
{
    int arr[] = {1,2,3,4,5,6,7};
    leftRotate(arr, 2, 7);
    printArray(arr, 7);
    return 0;
}

Java implementation:

class RotateArray {
    void leftRotate(int arr[], int k, int n) {
        for (int i = 0; i < k; i++) {
            leftRotateByOne(arr, n);
        }
    }
    
    void leftRotateByOne(int arr[], int n) {
        int temp = arr[0];
        for (int i = 0; i < n-1; i++){
            arr[i] = arr[i+1];
        }
        arr[n-1] = temp;
    }
}

Python implementation:

def leftRotate(arr, k, n):
    for i in range(k):
        leftRotateByOne(arr, n)
        
def leftRotateByOne(arr, n):
    temp = arr[0];
    for i in range(n-1):
        arr[i] = arr[i-1]
    arr[n-1] = temp

The important thing of algorithm is not implementation, but thought, but it can’t be realized without implementation.

Complexity analysis

  • Time complexity: O (KN)O(kn)
  • Space complexity: \ theta (1) Θ( 1)

Method 3 (maximum common divisor method)

This method is an extension of method 2. Method 2 moves elements step by step. This method moves elements according to the maximum common divisor of N and K.

For example, arr [] = {1,2,3,4,5,6,7,8,9,10,11,12}, k = 3, n = 12.

Calculate GCD (3,12) = 3. You only need to move 3 rounds to get the left rotation of the elements in the arraykResults from multiple locations.

Round 1: I = 0, temp = arr [i] = arr [0] = 1, move arr [J + k] to arr [J], note 0 < = j + k < n; I represents the counter of the number of moving wheels, and j represents the array subscript, as shown in Figure 3-1.

Figure 3-1 maximum common divisor method — round 1

Round 2: I = 1, temp = arr [1] = 2, move arr [J + 3] to arr [J], where 1 < = J < = 7. As shown in Figure 3-2.

Figure 3-2 maximum common divisor method — round 2

Round 3: I = 2, temp = arr [2] = 3, move arr [J + 3] to arr [J], where 2 < = J < = 8, as shown in Figure 3-3.

Figure 3-3 maximum common divisor method — round 3

Implementation code

C language

#include 
//Calculate the greatest common divisor GCD of K and n
int gcd(int a, int b){
    if(b == 0){
        return a;
    }
    else{
        return gcd(b, a % b);
    }
}

void leftRotate(int arr[], int k, int n){
    int i,j,s,temp;
    k = k % n; //  Can reduce unnecessary movement
    int g_ c_ d = gcd(k, n); //  Controls the number of times the outer loop is executed
    for(i = 0; i < g_c_d; i++){
        temp = arr[i]; //  1. Save arr [i] to temp
        j = i;
        //2. Move arr [J + k] to arr [J]
        while(1){
            s = j + k; //  Consider moving the elements of arr [J + k] to arr [J]
            If (s > = n) // exclude the case of j + k > = n, j + k < n
                s = s - n; 
            if (s == i) 
                break; 
            arr[j] = arr[s]; 
            j = s; 
        }
        arr[j] = temp; //  3. Save temp to arr [J]
    }
}

int main() 
{ 
    int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 }; 
    int i;
    leftRotate(arr, 3, 12); 
    for(i = 0; i < 12; i++){
        printf("%d ", arr[i]);
    }
    getchar(); 
    return 0; 
}

The process in the while loop is to move arr [J + k] to arr [J]. For example, in the first round of movement, the change of S is shown in Figure 3-4. Note that when s = j + K exceeds the boundary, the process is compared with the boundary value n of the array subscript. When s > = n, the subscript exceeds the boundary, then s = s – N, and then judge s = = I. if it is equal, exit the while loop, End of one round of movement:

Figure 3-4 change of subscript of rotation array in one round

Voluntary practice: try to simulate n = 12 and K = 8 by yourself(after practice, click the blank area below to view the reference answers).

Java implementation code

class RotateArray {
    //Rotate array arr to the left K positions
    void leftRotate(int arr[], int k, int n) {
        //Handle the case of k > = n, such as k = 13, n = 12
        k = k % n;
        int i, j, s, temp; // s = j + k;
        int gcd = gcd(k, n);
        for (i = 0; i < gcd; i++) {
            //Round I moving element
            temp = arr[i];
            j = i;
            while (true) {
                s = j + k;
                if (s >= n) {
                    s = s - n;
                }
                if (s == i) {
                    break;
                }
                arr[j] = arr[s];
                j = s;
            }
            arr[j] = temp;
        }
    }

    int gcd(int a, int b) {
        if(b == 0) {
            return a;
        }
        else{
            return gcd(b, a % b);
        }

    }

    public static void main(String[] args) {
        int arr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
        RotateArray ra = new RotateArray();
        ra.leftRotate(arr, 8, 12);
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + " ");
        }
    }
}

Python implementation

def leftRotate(arr, k, n):
    k = k % n
    g_c_d = gcd(k, n)
    for i in range(g_c_d):
        temp = arr[i]
        j = i
        while 1:
            s = j + k
            if s >= n:
                s = s - n
            if s == i:
                break
            arr[j] = arr[s]
            j = s
        arr[j] = temp

def gcd(a, b):
    if b == 0:
        return a
    else
        return gcd(b, a % b)

arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
n = len(arr)
leftRotate(arr, 3, n)
for i in range(n):
    print ("%d" % arr[i], end = " ")

Complexity analysis

  • Time complexity: O (n)O(n)
  • Space complexity: \ theta (1) Θ( 1)

Method 4 (block exchange method)

Array arr [] = [1,2,3,4,5,6,7], where k = 2 and N = 7.

Let the array arr [0,…, n-1] contain two blocks, a = arr [0,…, D-1], B = arr [D,…, n-1], then the result arr [] = [3,4,5,6,7,1,2] after rotating the array arr left for 2 positions is equivalent toAandBExchange, as shown in Figure 4-1.

Figure 4-1 block exchange method

Step 1: judgeAandBThe size of the,ALength ratio ofBSmall, thenBSplit intoBlandBrTwo parts, includingBrThe length of is equal toAThe length of the. exchangeAandBr, that is, the original arrayABlBrBecomeBrBlA。 hereAIt has been put in the right place, and then processed recursivelyBAs shown in Figure 4-2.

Figure 4-2 block switching method (ablbr — > brbla)

Step 2: recursive processingBPart, as shown in Figure 4-2BrIt’s newABlIt’s newB, judgeAandBThe processing is similar to the first step, as shown in Figure 4-3:

Figure 4-3 block exchange method (recursive processing part B)

Step 3: recursive processing part B, as shown in Figure 4-3BrIt’s newABlIt’s newB, judgeAandBThe size of the,ALength ratio ofBBig, willASplit intoAlandArTwo parts, includingAlThe length of is equal toBThe length of the. exchangeAlandB, thenAlArBBecomeBArAl, at this timeBHas returned to the right position; Recursive processingAAs shown in Figure 4-4.

Figure 4-4 block switching method (step 3)

Step 4: recursive processingA, in Figure 4-4AlIt’s newBArIt’s newA, at this timeAThe length of is equal toBLength, direct exchangeAandBAs shown in Figure 4-5.

Figure 4-5 block exchange method (recursive processing part a)

Implementation code

Recursive implementation

C language recursive implementation

#include 
//For block exchange, La is equivalent to the first element of block a and LB is equivalent to the first element of block B
void swap(int arr[], int la, int lb, int d) {
    int i, temp;
    for(i = 0; i < d; i++) {
        temp = arr[la+i];
        arr[la+i] = arr[lb+i];
        arr[lb+i] = temp;
    }
}

void leftRotate(int arr[], int k, int n) {
    if(k == 0 || k == n)
        return;
    //If the lengths of a and B are equal, exchange a and B directly
    if(n-k == k)
    {
        swap(arr, 0, n-k, k);
        return;
    }
    //If the length of a is less than B, B is divided into BL and Br, ablbr -- > brbla
    if(k < n-k)
    {
        swap(arr, 0, n-k, k);
        leftRotate(arr, k, n-k);
    }
    Else // if the length of a is greater than B, a is divided into Al and AR, alarb -- > Baral
    {
        swap(arr, 0, k, n-k);
        leftRotate(arr+n-k, 2*k-n, k);
    }
}

void printArray(int arr[], int size)
{
    int i;
    for(i = 0; i < size; i++)
        printf("%d ", arr[i]);
    printf("\n ");
} 

int main()
{
   int arr[] = {1, 2, 3, 4, 5, 6, 7};
   leftRotate(arr, 2, 7);
   printArray(arr, 7);
   getchar();
   return 0;
}

be careful:Arr + n-k represents an address value and represents the position of the first element of AR. Where the array name arr represents the first address of the first element in the array.

Java recursive implementation code

import java.util.*;

class BockSwap
{
    //Wrap recursive calls
    public static void leftRotate(int arr[], int k, int n)
    {
        leftRotateRec(arr, 0, k, n);
    }

    public static void leftRotateRec(int arr[], int i, int k, int n)
    {
        //If the number of rotations is 0 or N, exit directly without rotation
        if(k == 0 || k == n)
            return; 
         
        //In case of a = = B, swap (a, b)
        if(n - k == k)
        {
            swap(arr, i, n - k + i, k);
            return;
        }

        // A < B,swap(A,Br), ABlBr --> BrBlA
        if(k < n - k)
        {
            swap(arr, i, n - k + i, k);
            leftRotateRec(arr, i, k, n - k);
        }
        else // A > B , swap(Al, B), AlArB-->BArAl
        {
            swap(arr, i, k, n - k);
            leftRotateRec(arr, n - k + i, 2 * k - n, k);
        }
    }

    //Print
    public static void printArray(int arr[])
    {
        for(int i = 0; i < arr.length; i++)
            System.out.print(arr[i] + " ");
        System.out.println();
    }

    //Block switching
    public static void swap(int arr[], int la, int lb, int d)
    {
        int i, temp;
        for(i = 0; i < d; i++) {
            temp = arr[la+i];
            arr[la+i] = arr[lb+i];
            arr[lb+i] = temp;
        }
    }

    public static void main (String[] args)
    {
        int arr[] = {1, 2, 3, 4, 5, 6, 7};
        leftRotate(arr, 2, 7);
        printArray(arr);
    }
}

Python recursive code implementation

def leftRotate(arr, k, n):
    leftRotateRec(arr, 0, k, n);
 
def leftRotateRec(arr, i, k, n):
    
    if (k == 0 or k == n):
        return;

    if (n - k == k):
        swap(arr, i, n - k + i, k);
        return;
 
    if (k < n - k):
        swap(arr, i, n - k + i, k);
        leftRotateRec(arr, i, k, n - k);
    else:
        swap(arr, i, k, n - k);
        leftRotateRec(arr, n - k + i, 2 * k - n, k); 
 

def printArray(arr, size):
    for i in range(size):
        print(arr[i], end = " ");
    print();
 
def swap(arr, la, lb, d):
    for i in range(d):
        temp = arr[la + i];
        arr[la + i] = arr[lb + i];
        arr[lb + i] = temp;
 
if __name__ == '__main__':
    arr = [1, 2, 3, 4, 5, 6, 7];
    leftRotate(arr, 2, 7);
    printArray(arr, 7);

Iterative implementation

C language iterative implementation code:

void leftRotate(int arr[], int k, int n) {
    int i, j;
    if( k == 0 || k == n ) {
        return;
    }
    
    i = k;
    j = n - k;
    while (i != j) {
        if(i < j) // A < B
        {
            swap(arr, k-i, j-i+k, i);
            j -= i;
        }
        else {
            swap(arr, k-i, k, j);
            i -= j;
        }
    }
    swap(arr, k-i, k, i);
}

Java language iteration implementation code:

public static void leftRotate(int arr[], int d, int n) {
    int i, j;
    if (d == 0 || d == n)
        return;
    i = d;
    j = n - d;
    while (i != j) {
        if (i < j) {
            swap(arr, d - i, d + j - i, i);
            j -= i;
        } else {
            swap(arr, d - i, d, j);
            i -= j;
        }
    }
    swap(arr, d - i, d, i);
}

Python iterative implementation code:

def leftRotate(arr, k, n): 
    if(k == 0 or k == n): 
        return; 
    i = k 
    j = n - k 
    while (i != j): 
         
        if(i < j): # A < B 
            swap(arr, k - i, k + j - i, i) 
            j -= i 
         
        else: # A > B
            swap(arr, k - i, k, j) 
            i -= j 
     
    swap(arr, k - i, k, i) # A == B

Complexity analysis

  • Time complexity: O (n)O(n)
  • Space complexity: \ theta (1) Θ( 1)

Method 5 (inversion method)

The inversion method can also be used as the inversion method. It is known that the original array is arr [] = [1,2,3,4,5,6,7], and the array after two left-handed positions is [3,4,5,6,7,1,2]. Is there any method to obtain the original array from the rotated array?

First, reverse [3,4,5,6,7,1,2], as shown in Figure 5-4:

Figure 5-1 reverse (arr, 0, n)

Then, reverse [2,1] and [7,6,5,4,3] to obtain the results shown in Figure 5-2:

Figure 5-2 reverse (arr, 0, K), reverse (arr, K, n)

The algorithm of K left-handed positions of the array is as follows, as shown in Figure 5-3:

leftRotate(arr[], k, n)
    reverse(arr[], 0, k);
    reverse(arr[], k, n);
    reverse(arr[], 0, n);

Figure 5-3 inversion method (three steps)

Implementation code

#include  
void printArray(int arr[], int size); 
void reverseArray(int arr[], int start, int end); 
  
//Rotate the array left K positions
void leftRotate(int arr[], int k, int n) 
{ 
  
    if (k == 0 || k == n) 
        return; 
    //Prevent rotation parameter K from being greater than array length
    k = k % n; 
  
    reverseArray(arr, 0, k - 1); 
    reverseArray(arr, k, n - 1); 
    reverseArray(arr, 0, n - 1); 
} 
  
//Printout
void printArray(int arr[], int size) 
{ 
    int i; 
    for (i = 0; i < size; i++) 
        printf("%d ", arr[i]); 
} 
  
//Invert array
void reverseArray(int arr[], int start, int end) 
{ 
    int temp; 
    while (start < end) { 
        temp = arr[start]; 
        arr[start] = arr[end]; 
        arr[end] = temp; 
        start++; 
        end--; 
    } 
} 
  
//Main function
int main() 
{ 
    int arr[] = { 1, 2, 3, 4, 5, 6, 7 }; 
    int n = sizeof(arr) / sizeof(arr[0]); 
    int k = 2; 
  
    leftRotate(arr, k, n); 
    printArray(arr, n); 
    return 0; 
}

Complexity analysis

  • Time complexity: O (n)O(n)
  • Space complexity: \ theta (1) Θ( 1)

Algorithm is the way to solve the problem, and there are many ways to solve the problem, and what suits you is the best. Learn the algorithm well, and slowly you will find that your way of dealing with problems has changed, becoming more efficient and perfect!

In 2021, the bull spirit will soar! Don’t forget to brush 189 questions in leetcode!

 

The above article is from the official account: Jing Yu.

 

If you are a zero basis Xiaobai and want to learn programming, or programming beginners have no systematic understanding of programming. Here is a learning base recommended to you.

 

There will be a C language training camp once a week,From theory to practice, let you form programming thinking and understand how to make practical use of what you have learned.

containCIntroduction to languageCIntroduction to language related knowledge points and project practice.Help you understand the method of C language from theory to practice and form programming thinking.

Group containsCE-book resources related to language learning,CLinks to basic language course tutorials。 If you also want to get started with C language quickly, don’t miss the opportunity![click me to enter the learning base]