📜  生成排序数组所需的旋转计数

📅  最后修改于: 2021-09-06 11:29:50             🧑  作者: Mango

给定一个数组 arr[] ,任务是找到将给定数组转换为排序形式所需的旋转次数。
例子:

天真的方法:
为了解决上面提到的问题,第一个观察是如果我们在数组中有n 个元素,那么排序后,最大的元素在第 (n – 1)位置。在逆时针旋转 k 次后,最大的元素将位于索引 (k – 1)(从开始的k元素)。这里要注意的另一件事是,在旋转之后,最大元素的下一个元素将始终是最小元素(除非最大元素是最后一个索引,如果没有旋转,则可能)。
因此,

下面是上述方法的实现:

C++
// C++ program to find the
// count of rotations
#include 
using namespace std;
 
// Function to return the count
// of rotations
int countRotation(int arr[], int n)
{
    for(int i = 1; i < n; i++)
    {
         
       // Find the smallest element
       if (arr[i] < arr[i - 1])
       {
           // Return its index
           return i;
       }
    }
     
    // If array is not
    // rotated at all
    return 0;
}
 
// Driver Code
int main()
{
    int arr1[] = { 4, 5, 1, 2, 3 };
    int n = sizeof(arr1) / sizeof(int);
     
    cout << countRotation(arr1, n);
}
 
// This code is contributed by jrishabh99


Java
// Java Program to find the
// count of rotations
public class GFG {
 
    // Function to return the count of
    // rotations
    public static int countRotation(int[] arr,
                                    int n)
    {
        for (int i = 1; i < n; i++) {
            // Find the smallest element
            if (arr[i] < arr[i - 1]) {
                // Return its index
                return i;
            }
        }
        // If array is not
        // rotated at all
        return 0;
    }
 
    // Driver Code
    public static void main(String[] args)
    {
        int[] arr1 = { 4, 5, 1, 2, 3 };
 
        System.out.println(
            countRotation(
                arr1,
                arr1.length));
    }
}


Python3
# Python3 program to find the
# count of rotations
 
# Function to return the count
# of rotations
def countRotation(arr, n):
     
    for i in range (1, n):
         
        # Find the smallest element
        if (arr[i] < arr[i - 1]):
             
            # Return its index
            return i
     
    # If array is not
    # rotated at all
    return 0
 
# Driver Code
if __name__ == "__main__":
     
    arr1 = [ 4, 5, 1, 2, 3 ]
    n = len(arr1)
     
    print(countRotation(arr1, n))
 
# This code is contributed by chitranayal


C#
// C# program to find the count of rotations
using System;
class GFG{
 
// Function to return the count of
// rotations
public static int countRotation(int[] arr,
                                int n)
{
    for(int i = 1; i < n; i++)
    {
         
    // Find the smallest element
    if (arr[i] < arr[i - 1])
    {
             
        // Return its index
        return i;
    }
    }
     
    // If array is not
    // rotated at all
    return 0;
}
 
// Driver Code
public static void Main(String[] args)
{
    int[] arr1 = { 4, 5, 1, 2, 3 };
 
    Console.WriteLine(countRotation(arr1,
                                    arr1.Length));
}
}
 
// This code is contributed by gauravrajput1


Javascript


C++
// C++ program to implement the
// above approach
#include 
using namespace std;
 
// Function to return the
// count of rotations
int countRotation(int arr[], int low,
                             int high)
{
     
    // If array is not rotated
    if (low > high)
    {
        return 0;
    }
 
    int mid = low + (high - low) / 2;
 
    // Check if current element is
    // greater than the next
    // element
    if (mid < high && arr[mid] > arr[mid + 1])
    {
         
        // The next element is
        // the smallest
        return mid + 1;
    }
 
    // Check if current element is
    // smaller than it's previous
    // element
    if (mid > low && arr[mid] < arr[mid - 1])
    {
         
        // Current element is
        // the smallest
        return mid;
    }
 
    // Check if current element is
    // greater than lower bound
    if (arr[mid] > arr[low])
    {
         
        // The sequence is increasing
        // so far
        // Search for smallest
        // element on the right
        // subarray
        return countRotation(arr, mid + 1,
                             high);
    }
 
    if (arr[mid] < arr[high])
    {
         
        // Smallest element lies on the
        // left subarray
        return countRotation(arr, low,
                             mid - 1);
    }
    else
    {
         
        // Search for the smallest
        // element on both subarrays
        int rightIndex = countRotation(arr,
                                       mid + 1,
                                       high);
        int leftIndex = countRotation(arr, low,
                                      mid - 1);
        if (rightIndex == 0)
        {
            return leftIndex;
        }
        return rightIndex;
    }
}
 
// Driver code   
int main()
{
    int arr1[] = { 4, 5, 1, 2, 3 };
    int N = sizeof(arr1) / sizeof(arr1[0]);
     
    cout << countRotation(arr1, 0, N - 1);
     
    return 0;
}
 
// This code is contributed by divyeshrabadiya07


Java
// Java Program to implement
// the above approach
 
public class GFG {
 
    // Function to return the
    // count of rotations
    public static int countRotation(int[] arr,
                                    int low,
                                    int high)
    {
        // If array is not rotated
        if (low > high) {
            return 0;
        }
 
        int mid = low + (high - low) / 2;
 
        // Check if current element is
        // greater than the next
        // element
 
        if (mid < high
            && arr[mid] > arr[mid + 1]) {
            // the next element is
            // the smallest
            return mid + 1;
        }
 
        // Check if current element is
        // smaller than it's previous
        // element
        if (mid > low
            && arr[mid] < arr[mid - 1]) {
            // Current element is
            // the smallest
            return mid;
        }
 
        // Check if current element is
        // greater than lower bound
 
        if (arr[mid] > arr[low]) {
            // The sequence is increasing
            // so far
            // Search for smallest
            // element on the right
            // subarray
            return countRotation(arr,
                                mid + 1,
                                high);
        }
 
        if (arr[mid] < arr[high]) {
            // Smallest element lies on the
            // left subarray
            return countRotation(arr,
                                low,
                                mid - 1);
        }
 
        else {
            // Search for the smallest
            // element on both subarrays
            int rightIndex = countRotation(arr,
                                        mid + 1,
                                        high);
            int leftIndex = countRotation(arr,
                                        low,
                                        mid - 1);
 
            if (rightIndex == 0) {
                return leftIndex;
            }
 
            return rightIndex;
        }
    }
 
    // Driver Program
    public static void main(String[] args)
    {
        int[] arr1 = { 4, 5, 1, 2, 3 };
 
        System.out.println(
            countRotation(
                arr1,
                0, arr1.length
                    - 1));
    }
}


Python3
# Python3 program to implement the
# above approach
 
# Function to return the
# count of rotations
def countRotation(arr, low, high):
 
    # If array is not rotated
    if (low > high):
        return 0
 
    mid = low + (high - low) // 2
 
    # Check if current element is
    # greater than the next
    # element
    if (mid < high and arr[mid] > arr[mid + 1]):
 
        # The next element is
        # the smallest
        return mid + 1
 
    # Check if current element is
    # smaller than it's previous
    # element
    if (mid > low and arr[mid] < arr[mid - 1]):
 
        # Current element is
        # the smallest
        return mid
 
    # Check if current element is
    # greater than lower bound
    if (arr[mid] > arr[low]):
 
        # The sequence is increasing
        # so far
        # Search for smallest
        # element on the right
        # subarray
        return countRotation(arr, mid + 1, high)
 
    if (arr[mid] < arr[high]):
 
        # Smallest element lies on the
        # left subarray
        return countRotation(arr, low, mid - 1)
 
    else:
 
        # Search for the smallest
        # element on both subarrays
        rightIndex = countRotation(arr,
                                   mid + 1,
                                   high)
        leftIndex = countRotation(arr, low,
                                  mid - 1)
         
        if (rightIndex == 0):
            return leftIndex
 
        return rightIndex
 
# Driver code
if __name__ == '__main__':
     
    arr1 = [ 4, 5, 1, 2, 3 ]
    N = len(arr1)
 
    print(countRotation(arr1, 0, N - 1))
 
# This code is contributed by mohit kumar 29


C#
// C# program to implement
// the above approach
using System;
 
class GFG{
 
// Function to return the
// count of rotations
public static int countRotation(int[] arr,
                                int low,
                                int high)
{
 
    // If array is not rotated
    if (low > high)
    {
        return 0;
    }
 
    int mid = low + (high - low) / 2;
 
    // Check if current element is
    // greater than the next
    // element
    if (mid < high &&
        arr[mid] > arr[mid + 1])
    {
         
        // The next element is
        // the smallest
        return mid + 1;
    }
 
    // Check if current element is
    // smaller than it's previous
    // element
    if (mid > low &&
        arr[mid] < arr[mid - 1])
    {
         
        // Current element is
        // the smallest
        return mid;
    }
 
    // Check if current element is
    // greater than lower bound
    if (arr[mid] > arr[low])
    {
         
        // The sequence is increasing
        // so far
        // Search for smallest
        // element on the right
        // subarray
        return countRotation(arr,
                             mid + 1,
                             high);
    }
 
    if (arr[mid] < arr[high])
    {
         
        // Smallest element lies on the
        // left subarray
        return countRotation(arr, low,
                             mid - 1);
    }
     
    else
    {
         
        // Search for the smallest
        // element on both subarrays
        int rightIndex = countRotation(arr,
                                       mid + 1,
                                       high);
        int leftIndex = countRotation(arr, low,
                                      mid - 1);
 
        if (rightIndex == 0)
        {
            return leftIndex;
        }
        return rightIndex;
    }
}
 
// Driver code
public static void Main(String[] args)
{
    int[] arr1 = { 4, 5, 1, 2, 3 };
 
    Console.WriteLine(countRotation(arr1, 0,
                            arr1.Length - 1));
}
}
 
// This code is contributed by 29AjayKumar


输出:
2

时间复杂度: O(N)
辅助空间: O(1)

有效的方法:
为了优化上述方法,我们将使用二分搜索。我们可以注意到,在排序和旋转之后,给定的数组被分成两半,元素不减少,这是二分查找的唯一先决条件。在数组中执行递归二分查找以找到最小元素的索引。

下面是上述方法的实现:

C++

// C++ program to implement the
// above approach
#include 
using namespace std;
 
// Function to return the
// count of rotations
int countRotation(int arr[], int low,
                             int high)
{
     
    // If array is not rotated
    if (low > high)
    {
        return 0;
    }
 
    int mid = low + (high - low) / 2;
 
    // Check if current element is
    // greater than the next
    // element
    if (mid < high && arr[mid] > arr[mid + 1])
    {
         
        // The next element is
        // the smallest
        return mid + 1;
    }
 
    // Check if current element is
    // smaller than it's previous
    // element
    if (mid > low && arr[mid] < arr[mid - 1])
    {
         
        // Current element is
        // the smallest
        return mid;
    }
 
    // Check if current element is
    // greater than lower bound
    if (arr[mid] > arr[low])
    {
         
        // The sequence is increasing
        // so far
        // Search for smallest
        // element on the right
        // subarray
        return countRotation(arr, mid + 1,
                             high);
    }
 
    if (arr[mid] < arr[high])
    {
         
        // Smallest element lies on the
        // left subarray
        return countRotation(arr, low,
                             mid - 1);
    }
    else
    {
         
        // Search for the smallest
        // element on both subarrays
        int rightIndex = countRotation(arr,
                                       mid + 1,
                                       high);
        int leftIndex = countRotation(arr, low,
                                      mid - 1);
        if (rightIndex == 0)
        {
            return leftIndex;
        }
        return rightIndex;
    }
}
 
// Driver code   
int main()
{
    int arr1[] = { 4, 5, 1, 2, 3 };
    int N = sizeof(arr1) / sizeof(arr1[0]);
     
    cout << countRotation(arr1, 0, N - 1);
     
    return 0;
}
 
// This code is contributed by divyeshrabadiya07

Java

// Java Program to implement
// the above approach
 
public class GFG {
 
    // Function to return the
    // count of rotations
    public static int countRotation(int[] arr,
                                    int low,
                                    int high)
    {
        // If array is not rotated
        if (low > high) {
            return 0;
        }
 
        int mid = low + (high - low) / 2;
 
        // Check if current element is
        // greater than the next
        // element
 
        if (mid < high
            && arr[mid] > arr[mid + 1]) {
            // the next element is
            // the smallest
            return mid + 1;
        }
 
        // Check if current element is
        // smaller than it's previous
        // element
        if (mid > low
            && arr[mid] < arr[mid - 1]) {
            // Current element is
            // the smallest
            return mid;
        }
 
        // Check if current element is
        // greater than lower bound
 
        if (arr[mid] > arr[low]) {
            // The sequence is increasing
            // so far
            // Search for smallest
            // element on the right
            // subarray
            return countRotation(arr,
                                mid + 1,
                                high);
        }
 
        if (arr[mid] < arr[high]) {
            // Smallest element lies on the
            // left subarray
            return countRotation(arr,
                                low,
                                mid - 1);
        }
 
        else {
            // Search for the smallest
            // element on both subarrays
            int rightIndex = countRotation(arr,
                                        mid + 1,
                                        high);
            int leftIndex = countRotation(arr,
                                        low,
                                        mid - 1);
 
            if (rightIndex == 0) {
                return leftIndex;
            }
 
            return rightIndex;
        }
    }
 
    // Driver Program
    public static void main(String[] args)
    {
        int[] arr1 = { 4, 5, 1, 2, 3 };
 
        System.out.println(
            countRotation(
                arr1,
                0, arr1.length
                    - 1));
    }
}

蟒蛇3

# Python3 program to implement the
# above approach
 
# Function to return the
# count of rotations
def countRotation(arr, low, high):
 
    # If array is not rotated
    if (low > high):
        return 0
 
    mid = low + (high - low) // 2
 
    # Check if current element is
    # greater than the next
    # element
    if (mid < high and arr[mid] > arr[mid + 1]):
 
        # The next element is
        # the smallest
        return mid + 1
 
    # Check if current element is
    # smaller than it's previous
    # element
    if (mid > low and arr[mid] < arr[mid - 1]):
 
        # Current element is
        # the smallest
        return mid
 
    # Check if current element is
    # greater than lower bound
    if (arr[mid] > arr[low]):
 
        # The sequence is increasing
        # so far
        # Search for smallest
        # element on the right
        # subarray
        return countRotation(arr, mid + 1, high)
 
    if (arr[mid] < arr[high]):
 
        # Smallest element lies on the
        # left subarray
        return countRotation(arr, low, mid - 1)
 
    else:
 
        # Search for the smallest
        # element on both subarrays
        rightIndex = countRotation(arr,
                                   mid + 1,
                                   high)
        leftIndex = countRotation(arr, low,
                                  mid - 1)
         
        if (rightIndex == 0):
            return leftIndex
 
        return rightIndex
 
# Driver code
if __name__ == '__main__':
     
    arr1 = [ 4, 5, 1, 2, 3 ]
    N = len(arr1)
 
    print(countRotation(arr1, 0, N - 1))
 
# This code is contributed by mohit kumar 29

C#

// C# program to implement
// the above approach
using System;
 
class GFG{
 
// Function to return the
// count of rotations
public static int countRotation(int[] arr,
                                int low,
                                int high)
{
 
    // If array is not rotated
    if (low > high)
    {
        return 0;
    }
 
    int mid = low + (high - low) / 2;
 
    // Check if current element is
    // greater than the next
    // element
    if (mid < high &&
        arr[mid] > arr[mid + 1])
    {
         
        // The next element is
        // the smallest
        return mid + 1;
    }
 
    // Check if current element is
    // smaller than it's previous
    // element
    if (mid > low &&
        arr[mid] < arr[mid - 1])
    {
         
        // Current element is
        // the smallest
        return mid;
    }
 
    // Check if current element is
    // greater than lower bound
    if (arr[mid] > arr[low])
    {
         
        // The sequence is increasing
        // so far
        // Search for smallest
        // element on the right
        // subarray
        return countRotation(arr,
                             mid + 1,
                             high);
    }
 
    if (arr[mid] < arr[high])
    {
         
        // Smallest element lies on the
        // left subarray
        return countRotation(arr, low,
                             mid - 1);
    }
     
    else
    {
         
        // Search for the smallest
        // element on both subarrays
        int rightIndex = countRotation(arr,
                                       mid + 1,
                                       high);
        int leftIndex = countRotation(arr, low,
                                      mid - 1);
 
        if (rightIndex == 0)
        {
            return leftIndex;
        }
        return rightIndex;
    }
}
 
// Driver code
public static void Main(String[] args)
{
    int[] arr1 = { 4, 5, 1, 2, 3 };
 
    Console.WriteLine(countRotation(arr1, 0,
                            arr1.Length - 1));
}
}
 
// This code is contributed by 29AjayKumar
输出:
2

时间复杂度: O(N)
对于没有重复的数组,复杂度将为 O(logN)。但是如果数组包含重复项,那么它将递归调用对两半的搜索。所以最坏情况的复杂度将是 O(N)。

辅助空间: O(N)
在最坏的情况下,递归调用堆栈一次将有 N/2 个递归调用。

如果您想与行业专家一起参加直播课程,请参阅Geeks Classes Live