LeetCode - Rotate Array

Problem statement

Given an array, rotate the array to the right by k steps, where k is non-negative.

Problem statement taken from: https://leetcode.com/problems/rotate-array/.

Example 1:

Input: nums = [1, 2, 3, 4, 5, 6, 7], k = 3
Output: [5, 6, 7, 1, 2, 3, 4]

Explanation:
rotate 1 steps to the right: [7, 1, 2, 3, 4, 5, 6]
rotate 2 steps to the right: [6, 7, 1, 2, 3, 4, 5]
rotate 3 steps to the right: [5, 6, 7, 1, 2, 3, 4]

Example 2:

Input: nums = [-1, -100, 3, 99], k = 2
Output: [3, 99, -1, -100]

Explanation:
rotate 1 steps to the right: [99, -1, -100, 3]
rotate 2 steps to the right: [3, 99, -1, -100]

Constraints:

- 1 <= nums.length <= 10^5
- -2^31 <= nums[i] <= 2^31 - 1
- 0 <= k <= 10^5

Explanation

Brute force solution

The brute force approach is to create a temporary(temp) array and store the first k elements in the temp array. We then shift the rest of the array by k places and append back the tmp array to the original array.

The flow will look as below:

Input nums[] = [1, 2, 3, 4, 5, 6, 7], k = 2

1) Store the first k elements in a temp array
   temp[] = [1, 2]

2) Shift rest of the nums[]
   nums[] = [3, 4, 5, 6, 7, 6, 7]

3) Store back the k elements
   nums[] = [3, 4, 5, 6, 7, 1, 2]

The time complexity of the above approach is O(N) and space complexity is O(k).

Rotate one by one

If we want to avoid using extra space, we can rotate the array elements one by one.

We store the first element of the array in temp variable and shift nums[1] to nums[0], nums[2] to nums[1]... till the last element nums[n - 1] is shifted to nums[n - 2].

We repeat the above procedure k times.

The time complexity of the above approach is O(N*k) and space complexity if O(1).

Reversing an array

The problem can be solved in O(N) time by reversing array in parts. We consider array in two parts part1 = nums[0..k - 1] and part2 = nums[k..n - 1].

We reverse the elements present in the part1 array. We then reverse the part2 array elements. In the end, we reverse the entire array.

Let's check the algorithm to see how this solution works.

// rotate(nums, k)
- set n = nums.size()

- return if n == 1 or k == 0

- update k = k % n
  This is done when k is greater than n.
  eg n = 8, k = 12
  k = k % n
    = 12 % 8
    = 4

- call reverseArray(nums, 0, n - 1)
- call reverseArray(nums, 0, k - 1)
- call reverseArray(nums, k, n - 1)

// reverseArray(nums, start, end)
- while start < end
  - swap(nums[start], nums[end])
  - start++
  - end--

Let's check out our solutions in C++, Golang, and Javascript.

C++ solution

class Solution {
public:
    void reverseArray(vector<int>& nums, int start, int end) {
        while(start < end) {
            std::swap(nums[start], nums[end]);
            start++;
            end--;
        }
    }

    void rotate(vector<int>& nums, int k) {
        int n = nums.size();
        if(n == 1 || k == 0) {
            return;
        }

        k = k % n;
        reverseArray(nums, 0, n - 1);
        reverseArray(nums, 0, k - 1);
        reverseArray(nums, k, n - 1);
    }
};

Golang solution

func reverseArray(nums []int, start, end int) {
    for start < end {
        tmp := nums[start]
        nums[start] = nums[end]
        nums[end] = tmp
        start++
        end--
    }
}

func rotate(nums []int, k int)  {
    n := len(nums)

    if n == 1 || k == 0 {
        return
    }

    k = k % n

    reverseArray(nums, 0, n - 1)
    reverseArray(nums, 0, k - 1)
    reverseArray(nums, k, n - 1)
}

Javascript solution

var reverseArray = function(nums, start, end) {
    while(start < end) {
        let tmp = nums[start];
        nums[start] = nums[end];
        nums[end] = tmp;
        start++;
        end--;
    }
}

var rotate = function(nums, k) {
    let n = nums.length;

    if( n == 1 || k == 0 ) {
        return;
    }

    k = k % n;
    reverseArray(nums, 0, n - 1);
    reverseArray(nums, 0, k - 1);
    reverseArray(nums, k, n - 1);
};

Let's dry-run our algorithm to see how the solution works.

Input: nums = [1, 2, 3, 4, 5, 6, 7]
       k = 3

// rotate function
Step 1: n = nums.size()
          = 7

Step 2: n == 1 || k == 0
        7 == 1 || 3 == 0
        false

Step 3: k = k % n
          = 3 % 7
          = 3

Step 4: reverseArray(nums, 0, n - 1)
        reverseArray(nums, 0, 6)

// reverseArray(nums, start, end)
Step 5: while start < end
        0 < 6
        true

        swap(nums[0], nums[6])
        nums = [7, 2, 3, 4, 5, 6, 1]

        start++
        start = 1
        end--
        end = 5

Step 6: while start < end
        1 < 5
        true

        swap(nums[1], nums[5])
        nums = [7, 6, 3, 4, 5, 2, 1]

        start++
        start = 2
        end--
        end = 4

Step 7: while start < end
        2 < 4
        true

        swap(nums[2], nums[4])
        nums = [7, 6, 5, 4, 3, 2, 1]

        start++
        start = 3
        end--
        end = 3

Step 8: while start < end
        3 < 3
        false

// rotate function
Step 9: reverseArray(nums, 0, k - 1)
        reverseArray(nums, 0, 2)

// reverseArray(nums, start, end)
Step 10: while start < end
         0 < 2
         true

         swap(nums[0], nums[2])
         nums = [5, 6, 7, 4, 3, 2, 1]

         start++
         start = 1
         end--
         end = 1

Step 11: while start < end
         1 < 1
         false

// rotate function
Step 12: reverseArray(nums, k, n - 1)
         reverseArray(nums, 3, 6)

// reverseArray(nums, start, end)
Step 13: while start < end
         3 < 6
         true

         swap(nums[3], nums[6])
         nums = [5, 6, 7, 1, 3, 2, 4]

         start++
         start = 4
         end--
         end = 5

Step 14: while start < end
         4 < 5
         true

         swap(nums[4], nums[5])
         nums = [5, 6, 7, 1, 2, 3, 4]

         start++
         start = 5
         end--
         end = 4

Step 15: while start < end
         5 < 4
         false

// rotate function
no more steps to execute

We return the final array as [5, 6, 7, 1, 2, 3, 4].

Did you find this article valuable?

Support Alkesh Ghorpade by becoming a sponsor. Any amount is appreciated!