Summary

We have to rotate the elements of the given array k times to the right.

Solution


Approach #1 Brute Force [Time Limit Exceeded]

The simplest approach is to rotate all the elements of the array in k steps by rotating the elements by 1 unit in each step.

Java

public class Solution {
    public void rotate(int[] nums, int k) {
        int temp, previous;
        for (int i = 0; i < k; i++) {
            previous = nums[nums.length - 1];
            for (int j = 0; j < nums.length; j++) {
                temp = nums[j];
                nums[j] = previous;
                previous = temp;
            }
        }
    }
}

Complexity Analysis

  • Time complexity : . All the numbers are shifted by one step() k times().
  • Space complexity : . No extra space is used.

Approach #2 Using Extra Array [Accepted]

Algorithm

We use an extra array in which we place every element of the array at its correct position i.e. the number at index in the original array is placed at the index . Then, we copy the new array to the original one.

Java

public class Solution {
    public void rotate(int[] nums, int k) {
        int[] a = new int[nums.length];
        for (int i = 0; i < nums.length; i++) {
            a[(i + k) % nums.length] = nums[i];
        }
        for (int i = 0; i < nums.length; i++) {
            nums[i] = a[i];
        }
    }
}

Complexity Analysis

  • Time complexity : . One pass is used to put the numbers in the new array. And another pass to copy the new array to the original one.

  • Space complexity : . Another array of the same size is used.


Approach #3 Using Cyclic Replacements [Accepted]

Algorithm

We can directly place every number of the array at its required correct position. But if we do that, we will destroy the original element. Thus, we need to store the number being replaced in a variable. Then, we can place the replaced number() at its correct position and so on, times, where is the length of array. We have chosen to be the number of replacements since we have to shift all the elements of the array(which is ). But, there could be a problem with this method, if where (since a value of larger than eventually leads to a equivalent to ). In this case, while picking up numbers to be placed at the correct position, we will eventually reach the number from which we originally started. Thus, in such a case, when we hit the original number's index again, we start the same process with the number following it.

Now let's look at the proof of how the above method works. Suppose, we have as the number of elements in the array and is the number of shifts required. Further, assume . Now, when we start placing the elements at their correct position, in the first cycle all the numbers with their index satisfying get placed at their required position. This happens because when we jump k steps every time, we will only hit the numbers k steps apart. We start with index , having . Thus, we hit all the numbers satisfying the above condition in the first cycle. When we reach back the original index, we have placed elements at their correct position, since we hit only that many elements in the first cycle. Now, we increment the index for replacing the numbers. This time, we place other elements at their correct position, different from the ones placed correctly in the first cycle, because this time we hit all the numbers satisfy the condition . When we hit the starting number again, we increment the index and repeat the same process from for all the indices satisfying . This happens till we reach the number with the index again, which occurs for . We will reach such a number after a total of k cycles. Now, the total count of numbers exclusive numbers placed at their correct position will be . Thus, all the numbers will be placed at their correct position.

Look at the following example to clarify the process: nums: [1, 2, 3, 4, 5, 6] k: 2

Rotate Array

java

public class Solution {
    public void rotate(int[] nums, int k) {
        k = k % nums.length;
        int count = 0;
        for (int start = 0; count < nums.length; start++) {
            int current = start;
            int prev = nums[start];
            do {
                int next = (current + k) % nums.length;
                int temp = nums[next];
                nums[next] = prev;
                prev = temp;
                current = next;
                count++;
            } while (start != current);
        }
    }
}

Complexity Analysis

  • Time complexity : . Only one pass is used.

  • Space complexity : . Constant extra space is used.


Approach #4 Using Reverse [Accepted]

Algorithm

This approach is based on the fact that when we rotate the array k times, elements from the back end of the array come to the front and the rest of the elements from the front shift backwards.

In this approach, we firstly reverse all the elements of the array. Then, reversing the first k elements followed by reversing the rest elements gives us the required result.

Let and .

Original List                   : 1 2 3 4 5 6 7
After reversing all numbers     : 7 6 5 4 3 2 1
After reversing first k numbers : 5 6 7 4 3 2 1
After revering last n-k numbers : 5 6 7 1 2 3 4 --> Result

java

public class Solution {
    public void rotate(int[] nums, int k) {
        k %= nums.length;
        reverse(nums, 0, nums.length - 1);
        reverse(nums, 0, k - 1);
        reverse(nums, k, nums.length - 1);
    }
    public void reverse(int[] nums, int start, int end) {
        while (start < end) {
            int temp = nums[start];
            nums[start] = nums[end];
            nums[end] = temp;
            start++;
            end--;
        }
    }
}

Complexity Analysis

  • Time complexity : . elements are reversed a total of three times.

  • Space complexity : . No extra space is used.

Analysis written by: @vinod23