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

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

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

输入: arr[] = {4, 5, 1, 2, 3}

输出: 2

解释:

需要2次逆时针旋转后形成排序数组{1, 2, 3, 4, 5}。

输入: arr[] = {2, 1, 2, 2, 2}

输出: 1

解释:

需要1次逆时针旋转后形成排序数组{1, 2, 2, 2, 2}。

Naive Approach:

为了解决上述问题,我们首先观察到,如果数组中有 n 个元素,则排序后最大的元素位于第(n – 1)个位置。进行k次逆时针旋转后,最大元素将位于索引(k – 1)(从开始数的第k个元素)。另外一个需要注意的是,旋转后最大元素的下一个元素始终是最小元素(除非最大元素在最后一个索引上,如果没有旋转就可能出现)。
因此,

旋转次数(k) = 数组中最小元素的索引(k)

下面是实现上述方法的代码:

// C++ program to find the
// count of rotations
#include <bits/stdc++.h> 
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```  

输出:

2

时间复杂度: O(N)

辅助空间: O(1)

Efficient Approach:

为了优化上述方法,我们将使用二分查找。我们可以注意到,在排序并旋转后,给定的数组被分成两个具有非递减元素的部分,这是二分查找的唯一前提条件。在数组中执行递归二分查找以找到最小元素的索引。

下面是实现上述方法的代码:

// C++程序实现如上方法
#include <bits/stdc++.h>
using namespace std;

// 返回旋转次数的函数
int countRotation(int arr[], int low,
                                    int high)
{   

    // 如果数组没有旋转
    if (low > high)
    {   
        return 0;   
    }   

    int mid = low + (high - low) / 2;   

    // 检查当前元素是否大于下一个元素
    if (mid < high && arr[mid] > arr[mid + 1])
    {   

        // 下一个元素是最小的
        return mid + 1;   
    }   

    // 检查当前元素是否小于它的前一个元素
    if (mid > low && arr[mid] < arr[mid - 1])
    {   

        // 当前元素是最小的
        return mid;   
    }   

    // 检查当前元素是否大于下界
    if (arr[mid] > arr[low])   
    {

        // 序列迄今为止增加
        // 在右子阵列中搜索最小元素
        return countRotation(arr, mid + 1,
                                                high);  
    }   

    if (arr[mid] < arr[high])
    {   

        // 最小元素在左子阵列上
        return countRotation(arr, low,
                                                mid - 1);  
    }   
    else   
    {   

        // 在两个子阵列上搜索最小元素
        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;
}

// 该代码由divyeshrabadiya07贡献```  

输出:

2

时间复杂度: O(N)

对于没有重复项的数组,复杂性将为O(logN)。但是,如果数组包含重复项,则它将递归地调用搜索来寻找两个半部分。因此,最坏情况下的复杂度将是O(N)。

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

Python教程

Java教程

Web教程

数据库教程

图形图像教程

大数据教程

开发工具教程

计算机教程

C++ 示例