Rotation Count in a Rotated Sorted array
Given an array arr[] having distinct numbers sorted in increasing order and the array has been right rotated (i.e, the last element will be cyclically shifted to the starting position of the array) k number of times, the task is to find the value of k.
Examples:
Input: arr[] = {15, 18, 2, 3, 6, 12}
Output: 2
Explanation: Initial array must be {2, 3, 6, 12, 15, 18}.
We get the given array after rotating the initial array twice.Input: arr[] = {7, 9, 11, 12, 5}
Output: 4Input: arr[] = {7, 9, 11, 12, 15};
Output: 0
Naive Approach – O(n) Time and O(1) Space
If we take a closer look at examples, we can notice that the number of rotations is equal to the index of the minimum element. A simple linear solution is to find the minimum element and returns its index.
#include <bits/stdc++.h>
using namespace std;
// Returns count of rotations for an array which
// is first sorted in ascending order, then rotated
int countRotations(vector<int>& arr)
{
// Find index of minimum element
int min = arr[0], min_index = 0;
for (int i = 0; i < arr.size(); i++) {
if (min > arr[i]) {
min = arr[i];
min_index = i;
}
}
return min_index;
}
// Driver code
int main()
{
vector<int> arr = { 15, 18, 2, 3, 6, 12 };
cout << countRotations(arr);
return 0;
}
// C program to find number of rotations
// in a sorted and rotated array.
#include <stdio.h>
// Returns count of rotations for an array which
// is first sorted in ascending order, then rotated
int countRotations(int arr[], int n)
{
// We basically find index of minimum
// element
int min = arr[0], min_index = 0;
for (int i = 0; i < n; i++) {
if (min > arr[i]) {
min = arr[i];
min_index = i;
}
}
return min_index;
}
// Driver code
int main()
{
int arr[] = { 15, 18, 2, 3, 6, 12 };
int n = sizeof(arr) / sizeof(arr[0]);
printf("%d", countRotations(arr, n));
return 0;
}
// This code is contributed by Adutya Kumar(adityakumar129)
// Java program to find number of
// rotations in a sorted and rotated
// array.
import java.io.*;
import java.lang.*;
import java.util.*;
class LinearSearch {
// Returns count of rotations for an
// array which is first sorted in
// ascending order, then rotated
static int countRotations(int arr[], int n)
{
// We basically find index of minimum
// element
int min = arr[0], min_index = 0;
for (int i = 0; i < n; i++) {
if (min > arr[i]) {
min = arr[i];
min_index = i;
}
}
return min_index;
}
// Driver program to test above functions
public static void main(String[] args)
{
int arr[] = { 15, 18, 2, 3, 6, 12 };
int n = arr.length;
System.out.println(countRotations(arr, n));
}
}
// This code is contributed by Adutya Kumar(adityakumar129)
# Python3 program to find number
# of rotations in a sorted and
# rotated array.
# Returns count of rotations for
# an array which is first sorted
# in ascending order, then rotated
def countRotations(arr, n):
# We basically find index
# of minimum element
min = arr[0]
min_index = 0
for i in range(0, n):
if (min > arr[i]):
min = arr[i]
min_index = i
return min_index;
# Driver code
arr = [15, 18, 2, 3, 6, 12]
n = len(arr)
print(countRotations(arr, n))
# This code is contributed by Smitha Dinesh Semwal
// c# program to find number of
// rotations in a sorted and rotated
// array.
using System;
class LinearSearch
{
// Returns count of rotations for an
// array which is first sorted in
// ascending order, then rotated
static int countRotations(int []arr, int n)
{
// We basically find index of minimum
// element
int min = arr[0], min_index = 0;
for (int i = 0; i < n; i++)
{
if (min > arr[i])
{
min = arr[i];
min_index = i;
}
}
return min_index;
}
// Driver program to test above functions
public static void Main ()
{
int []arr = {15, 18, 2, 3, 6, 12};
int n = arr.Length;
Console.WriteLine(countRotations(arr, n));
}
}
// This code is contributed by vt_m.
<script>
// Javascript program to find number of rotations
// in a sorted and rotated array.
// Returns count of rotations for an array which
// is first sorted in ascending order, then rotated
function countRotations(arr, n)
{
// We basically find index of minimum
// element
let min = arr[0], min_index = 0
for (let i = 0; i < n; i++)
{
if (min > arr[i])
{
min = arr[i];
min_index = i;
}
}
return min_index;
}
// Driver Code
let arr = [15, 18, 2, 3, 6, 12];
let n = arr.length;
document.write(countRotations(arr, n));
</script>
<?php
// PHP program to find number
// of rotations in a sorted
// and rotated array.
// Returns count of rotations
// for an array which is first
// sorted in ascending order,
// then rotated
function countRotations($arr, $n)
{
// We basically find index
// of minimum element
$min = $arr[0];
$min_index = 0;
for ($i = 0; $i < $n; $i++)
{
if ($min > $arr[$i])
{
$min = $arr[$i];
$min_index = $i;
}
}
return $min_index;
}
// Driver code
$arr = array(15, 18, 2,
3, 6, 12);
$n = sizeof($arr);
echo countRotations($arr, $n);
// This code is contributed
// by ajit
?>
Output
2
Expected Approach – O(Log n) Time and O(1) Space
As we have seen above, this problem is mainly a variation find the smallest element in the array. The only change here is, we need to find the index of the minimum element instead of the value.
In Binary Search, we find the mid element and then decide whether to stop or to go to left half or right half. How do we decide in this case. Let us take few examples.
{4, 5, 6, 9, 0, 1, 2}, mid = (0 + 7) / 2 = 3. arr[3] is 9. How do find out that we need to go to the right half (Note that the smallest element is in right half)? We can say if arr[mid] > arr]high], then we go the right half. So we change low = mid + 1.
{50, 10, 20, 30, 40}, mid = (0 + 4)/2 = 2. arr[2] is 20. If arr[mid] is smaller than or equal to arr[high], then we go to the left half.
How do we terminate the search? One way could be to check if the mid is smaller than both of its adjacent, then we return mid. This would require a lot of condition checks like if adjacent indexes are valid or not and then comparing mid with both. We use an interesting fact here. If arr[low] <= arr[high], then the current subarray must be sorted, So we return arr[low]. This optimizes the code drastically as we do not have to explicitly check the whole sorted array.
Below is the implementation of the above approach.
#include <bits/stdc++.h>
using namespace std;
int findMin(vector<int> &arr)
{
int low = 0, high = arr.size() - 1;
while (low < high)
{
// The current subarray is already sorted,
// the minimum is at the low index
if (arr[low] <= arr[high])
return low;
// We reach here when we have at least
// two elements and the current subarray
// is rotated
int mid = (low + high) / 2;
// The right half is not sorted. So
// the minimum element must be in the
// right half.
if (arr[mid] > arr[high])
low = mid + 1;
// The right half is sorted. Note that in
// this case, we do not change high to mid - 1
// but keep it to mid. Ad the mid element
// etself can be the smallest
else
high = mid;
}
return low;
}
// Driver program to test above functions
int main()
{
vector<int> arr = {5, 6, 1, 2, 3, 4};
cout << findMin(arr);
return 0;
}
// Java program to find number of
// rotations in a sorted and rotated
// array.
import java.io.*;
import java.lang.*;
import java.util.*;
class BinarySearch {
// Returns count of rotations for an array
// which is first sorted in ascending order,
// then rotated
static int countRotations(int arr[], int low, int high)
{
// This condition is needed to handle
// the case when array is not rotated
// at all
if (high < low)
return 0;
// If there is only one element left
if (high == low)
return low;
// Find mid
// /*(low + high)/2;*/
int mid = low + (high - low) / 2;
// Check if element (mid+1) is minimum
// element. Consider the cases like
// {3, 4, 5, 1, 2}
if (mid < high && arr[mid + 1] < arr[mid])
return (mid + 1);
// Check if mid itself is minimum element
if (mid > low && arr[mid] < arr[mid - 1])
return mid;
// Decide whether we need to go to left
// half or right half
if (arr[high] > arr[mid])
return countRotations(arr, low, mid - 1);
return countRotations(arr, mid + 1, high);
}
// Driver program to test above functions
public static void main(String[] args)
{
int arr[] = { 15, 18, 2, 3, 6, 12 };
int N = arr.length;
System.out.println(countRotations(arr, 0, N - 1));
}
}
// This code is contributed by Chhavi
# Returns count of rotations for an array which
# is first sorted in ascending order, then rotated
def countRotations(arr, low, high):
# This condition is needed to handle the case
# when the array is not rotated at all
if high < low:
return 0
# If there is only one element left
if high == low:
return low
# Find mid
mid = low + (high - low) // 2
# Check if element (mid+1) is minimum element.
# Consider the cases like {3, 4, 5, 1, 2}
if mid < high and arr[mid + 1] < arr[mid]:
return mid + 1
# Check if mid itself is minimum element
if mid > low and arr[mid] < arr[mid - 1]:
return mid
# Decide whether we need to go to left half or
# right half
if arr[high] > arr[mid]:
return countRotations(arr, low, mid - 1)
return countRotations(arr, mid + 1, high)
# Driver code
if __name__ == "__main__":
arr = [15, 18, 2, 3, 6, 12]
N = len(arr)
print(countRotations(arr, 0, N - 1))
// C# program to find number of
// rotations in a sorted and rotated
// array.
using System;
class BinarySearch {
// Returns count of rotations for an array
// which is first sorted in ascending order,
// then rotated
static int countRotations(int[] arr, int low, int high)
{
// This condition is needed to handle
// the case when array is not rotated
// at all
if (high < low)
return 0;
// If there is only one element left
if (high == low)
return low;
// Find mid
// /*(low + high)/2;*/
int mid = low + (high - low) / 2;
// Check if element (mid+1) is minimum
// element. Consider the cases like
// {3, 4, 5, 1, 2}
if (mid < high && arr[mid + 1] < arr[mid])
return (mid + 1);
// Check if mid itself is minimum element
if (mid > low && arr[mid] < arr[mid - 1])
return mid;
// Decide whether we need to go to left
// half or right half
if (arr[high] > arr[mid])
return countRotations(arr, low, mid - 1);
return countRotations(arr, mid + 1, high);
}
// Driver program to test above functions
public static void Main()
{
int[] arr = { 15, 18, 2, 3, 6, 12 };
int N = arr.Length;
Console.WriteLine(countRotations(arr, 0, N - 1));
}
}
// This code is contributed by vt_m.
<script>
// Binary Search based C++ program to find number
// of rotations in a sorted and rotated array.
// Returns count of rotations for an array which
// is first sorted in ascending order, then rotated
function countRotations(arr, low, high)
{
// This condition is needed to handle the case
// when the array is not rotated at all
if (high < low)
return 0;
// If there is only one element left
if (high == low)
return low;
// Find mid
let mid = Math.floor(low + (high - low)/2); /*(low + high)/2;*/
// Check if element (mid+1) is minimum element.
// Consider the cases like {3, 4, 5, 1, 2}
if (mid < high && arr[mid+1] < arr[mid])
return (mid+1);
// Check if mid itself is minimum element
if (mid > low && arr[mid] < arr[mid - 1])
return mid;
// Decide whether we need to go to left half or
// right half
if (arr[high] > arr[mid])
return countRotations(arr, low, mid-1);
return countRotations(arr, mid+1, high);
}
// Driver code
let arr = [15, 18, 2, 3, 6, 12];
let N = arr.length;
document.write(countRotations(arr, 0, N-1));
// This code is contributed by Surbhi Tyagi.
</script>
<?php
// Binary Search based PHP
// program to find number
// of rotations in a sorted
// and rotated array.
// Returns count of rotations
// for an array which is
// first sorted in ascending
// order, then rotated
function countRotations($arr,
$low, $high)
{
// This condition is needed
// to handle the case when
// array is not rotated at all
if ($high < $low)
return 0;
// If there is only
// one element left
if ($high == $low)
return $low;
// Find mid
$mid = $low + ($high -
$low) / 2;
// Check if element (mid+1)
// is minimum element. Consider
// the cases like {3, 4, 5, 1, 2}
if ($mid < $high &&
$arr[$mid + 1] < $arr[$mid])
return (int)($mid + 1);
// Check if mid itself
// is minimum element
if ($mid > $low &&
$arr[$mid] < $arr[$mid - 1])
return (int)($mid);
// Decide whether we need
// to go to left half or
// right half
if ($arr[$high] > $arr[$mid])
return countRotations($arr, $low,
$mid - 1);
return countRotations($arr,
$mid + 1,
$high);
}
// Driver code
$arr = array(15, 18, 2, 3, 6, 12);
$N = sizeof($arr);
echo countRotations($arr, 0, $N - 1);
// This code is contributed bu ajit
?>
Output
2