Problem Statement

Given an integer array nums of size n, sorted in ascending order with distinct values. The array has been right rotated an unknown number of times, between 1 and n. Determine the number of rotations performed on the array.

Examples

Example 1:

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

Explanation: The original array should be [0, 1, 2, 3, 4, 5, 6, 7]. So we can notice that the array has been roated 4 times.
Input 2:

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

Explanation: The original array should be [1, 3, 4, 5, 6]. So, we can notice that the array has been roated 1 time.

Different Approaches

1️⃣ Brute Force (Linear Search)

Intuition:

The straightforward solution to this problem involves performing a simple linear search to find the minimum element of the array by comparing each element individually. The index at which the minimum element is found corresponds to the number of times the array has been rotated. Since the array was initially sorted, the smallest element would have been at the front. Therefore, the index of this smallest element gives the number of rotations because it indicates how many positions the array has been shifted.

Approach:

  1. First, declare an ans and an index variable initialized with a INT_MAX and -1 respectively.
  2. Next, iterate through the array and compare each element with the variable called ans. Whenever an element is encountered such that it is smaller than ans, update ans with that value and also update the index variable with the current index.
  3. Finally, we will return index as our answer.

Dry Run:

Initialization:
minimum = INT_MAX
index = -1
    +-----+-----+-----+-----+-----+
arr |  3  |  4  |  5  |  1  |  2  |
    +-----+-----+-----+-----+-----+
       0     1     2     3     4
First Iteration:
minimum = INT_MAX
index = -1

    +-----+-----+-----+-----+-----+
arr |  3  |  4  |  5  |  1  |  2  |
    +-----+-----+-----+-----+-----+
       0     1     2     3     4
       ^
       |
       i

If arr[index] < minimum
   True
   set minimum = min(minimum, arr[index])
       minimum = min(INT_MAX, 3)
       minimum = 3
       index = i
       index = 0
   i++
Second Iteration:
minimum = 3
index = 0

    +-----+-----+-----+-----+-----+
arr |  3  |  4  |  5  |  1  |  2  |
    +-----+-----+-----+-----+-----+
       0     1     2     3     4
             ^
             |
             i

If arr[index] < minimum
   False
   i++
Third Iteration:
minimum = 3
index = 0

    +-----+-----+-----+-----+-----+
arr |  3  |  4  |  5  |  1  |  2  |
    +-----+-----+-----+-----+-----+
       0     1     2     3     4
                   ^
                   |
                   i

If arr[index] < minimum
   False
   i++
Fourth Iteration:
minimum = 3
index = 0

    +-----+-----+-----+-----+-----+
arr |  3  |  4  |  5  |  1  |  2  |
    +-----+-----+-----+-----+-----+
       0     1     2     3     4
                         ^
                         |
                         i

If arr[index] < minimum
   True
   set minimum = min(minimum, arr[index])
       minimum = min(3, 1)
       minimum = 1
       index = i
       index = 3
   i++
Fifth Iteration:
minimum = 1
index = 3

    +-----+-----+-----+-----+-----+
arr |  3  |  4  |  5  |  1  |  2  |
    +-----+-----+-----+-----+-----+
       0     1     2     3     4
                               ^
                               |
                               i

If arr[index] < minimum
   False
   i++
Loop Termination:
minimum = 1
index = 3

    +-----+-----+-----+-----+-----+
arr |  3  |  4  |  5  |  1  |  2  |
    +-----+-----+-----+-----+-----+
       0     1     2     3     4      5
                                      ^
                                      |
                                      i

As i exceeds the bounds of the array,
So loop will terminate
and return index (3), which means
this is rotated to right three times.

Code:

#include <bits/stdc++.h>  
using namespace std;      

class Solution {
public:
    /* Function to find the number of
    rotations in a rotated sorted array */
    int findKRotation(vector<int>& nums) {
        
        // Get the size of the array
        int n = nums.size();  
        
        /* Initialize variables to store
        minimum value and its index*/
        int ans = INT_MAX, index = -1;  
        
        /* Iterate through the array to
        find the smallest element */
        for (int i = 0; i < n; i++) {
            if (nums[i] < ans) {  
                ans = nums[i];  
                index = i;      
            }
        }
        // Return the index of smallest element
        return index;  
    }
};

int main() {
    vector<int> nums = {4, 5, 6, 7, 0, 1, 2, 3};  
    
    // Create an object of the Solution class
    Solution sol;  
    
    int ans = sol.findKRotation(nums);  
    
    // Print the result
    cout << "The array is rotated " << ans << " times.\n";
    
    return 0;  
}

Complexity Analysis:

  • Time Complexity: O(N), where N is size of the array. As the array is being traversed only once using a single loop.
  • Space Complexity: As no additional space is used, so the Space Complexity is O(1).

2️⃣ Optimal (Binary Search)

Intuition:

The idea here is to use the binary search algorithm to determine the index at which the minimum element of the array is located. This index will indicate the number of times the array has been rotated. Observing this, it's analogous to finding the minimum element in a rotated sorted array. Here, the additional requirement is to return the index of the minimum element rather than the element itself.

Approach:

  1. First, initialize few variables: low to 0 (beginning of the array, high to (end of the array), ans to Integer MAX_VALUE to track the minimum element found during the search, index to -1 to store the index of the minimum element.
  2. Use a binary search strategy to efficiently find the minimum element in the rotated sorted array, which directly gives the number of rotations. While low is less than or equal to high, calculate the middle index mid.
  3. If element at low is less than or equal to element at high, the search space is already sorted. In this case, element at low is the smallest element, representing the start of the rotation. Update ans and index accordingly and break out of the loop.
  4. Determine whether the left part of the array is sorted or the right part of the array is sorted
  5. If the left part is sorted (element at (low) <= element at (mid)):
    1. Check if element at (low) is less than ans. If so, update ans and index to reflect the new minimum element found.
    2. Adjust low to mid + 1 to search the right half, as the rotation point (minimum element) must be on the right side.
  6. If the right part is sorted (element at (low) > element at (mid)):
    1. Check if element at (mid) is less than ans. If so, update ans and index accordingly.
    2. Adjust high to mid - 1 to search the left half.
  7. Once the loop completes, index will hold the index of the minimum element, which represents the number of rotations. Return index as the answer.

Dry Run:

Initialization:
minimum = INT_MAX
index = -1

    +-----+-----+-----+-----+-----+
arr |  3  |  4  |  5  |  1  |  2  |
    +-----+-----+-----+-----+-----+
       0     1     2     3     4
First Iteration:
minimum = INT_MAX
index = -1

Left = 0
Right = 4
Mid = Left + (Right - Left) / 2
    = 0 + (4 - 0) / 2
    = 4 / 2
    = 2

    +-----+-----+-----+-----+-----+
arr |  3  |  4  |  5  |  1  |  2  |
    +-----+-----+-----+-----+-----+
       0     1     2     3     4
       ^           ^           ^
       |           |           |
      Left        Mid         Right

Is arr[Left] <= arr[Right]
   3 <= 2
   False, this means array is not sorted at complete.

Is arr[Left] <= arr[Mid]
   3 <= 5
   True
   If arr[Left] < minimum
      3 < INT_MAX
      True
      Set minimum = arr[Left]
          minimum = 3
          index = Left
          index = 0
      // Go to Right side now (Eliminate Left Half)
      Left = Mid + 1
           = 2 + 1
           = 3
Second Iteration:
minimum = 3
index = 0

Left = 3
Right = 4
Mid = Left + (Right - Left) / 2
    = 3 + (4 - 3) / 2
    = 3 + 1/ 2
    = 3 + 0
    = 3

    +-----+-----+-----+-----+-----+
arr |  3  |  4  |  5  |  1  |  2  |
    +-----+-----+-----+-----+-----+
       0     1     2     3     4
                         ^     ^
                         |     |
                        Left  Right
                        Mid

Is arr[Left] <= arr[Right]
   1 <= 2
   True, this means array is sorted at complete.
   If arr[Left] < minimum
      1 < 3
      True
      Set minimum = arr[Left]
          minimum = 1
          index = Left
          index = 3
      Since this part of the array was sorted
      and we set the very extreme left element
      to the minimum.
      Now we no further need to check again.
      So break the loop
      and return index, which is 3.

Code:

#include <bits/stdc++.h>
using namespace std;

class Solution {
public:
    /* Function to find the number of
       rotations in a rotated sorted array */
    int findKRotation(vector<int>& nums) {
        int low = 0, high = nums.size() - 1;
        int ans = INT_MAX;
        int index = -1;
        while (low <= high) {
            int mid = (low + high) / 2;
            
            /* Search space is already sorted
            then nums[low] will always be
            the minimum in that search space */
            if (nums[low] <= nums[high]) {
                if (nums[low] < ans) {
                    index = low;
                    ans = nums[low];
                }
                break;
            }
            // If left part is sorted update the ans
            if (nums[low] <= nums[mid]) {
                if (nums[low] < ans) {
                    index = low;
                    ans = nums[low];
                }
                // Eliminate left half
                low = mid + 1;
            }
            else { 
                /*update the ans if it 
                is less than nums[mid] */
                if (nums[mid] < ans) {
                    index = mid;
                    ans = nums[mid];
                }
                // Eliminate right half
                high = mid - 1;
            }
        }
        //Return the index as answer
        return index;
    }
};

int main() {
    vector<int> nums = {4, 5, 6, 7, 0, 1, 2, 3}; 
    
    // Create an object of the Solution class
    Solution sol;
    
    int ans = sol.findKRotation(nums);
    
    // Print the result
    cout << "The array is rotated " << ans << " times.\n";
    
    return 0;
}

Complexity Analysis:

  • Time Complexity: O(logN), where N is size of the array. As binary search algorithm is being applied to solve the problem.
  • Space Complexity: As no additional space is used, so the Space Complexity is O(1).