📌  相关文章
📜  C ++程序计算生成排序数组所需的旋转次数

📅  最后修改于: 2022-05-13 01:55:37.131000             🧑  作者: Mango

C ++程序计算生成排序数组所需的旋转次数

给定一个数组 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


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


输出:
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
输出:
2

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

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

有关详细信息,请参阅有关生成排序数组所需的旋转计数的完整文章!