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

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

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

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

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

下面是上述方法的实现:

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


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


输出:
2

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

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

下面是上述方法的实现:

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

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

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

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