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

📅  最后修改于: 2021-05-17 16:17:15             🧑  作者: 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


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)); 
    } 
} 

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(logN)。但是,如果数组包含重复项,则它将递归地调用两个部分的搜索。因此,最坏情况下的复杂度将是O(N)。
辅助空间: O(N)
在最坏的情况下,递归调用堆栈一次将具有N / 2个递归调用。