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

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

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

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

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

下面是上述方法的实现:

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


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


输出:
2

时间复杂度: O(N)
辅助空间: O(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
输出:
2

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

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

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