📌  相关文章
📜  使用二进制搜索检查数组是否已排序和旋转

📅  最后修改于: 2021-04-26 06:48:37             🧑  作者: Mango

先决条件:检查是否使用线性搜索对数组进行了排序和旋转
给定N个不同整数的数组arr [] ,任务是检查逆时针旋转时此数组是否已排序。已排序的数组不被视为已排序和旋转,即应该至少旋转一圈。
例子:

方法:本文已经讨论了使用线性搜索解决此问题的一种方法。
在本文中,提到了一种使用二进制搜索概念的方法。

  • 要应用二进制搜索,数组需要遵循某种顺序,通过该顺序,每次迭代都可以消除数组的一半。
  • 因此,对数组进行排序和旋转后的数组的顺序是,枢轴左侧的所有元素(阵列旋转的点)都按降序排列,而枢轴右侧的所有元素都将按降序排列升序排列。
    可以从下面的插图中看到:

  • 因此,可以通过以下方式使用二进制搜索和递归来找到枢轴:
    • 基本案例:基本案例将是在找到枢轴时或在给定数组中找不到枢轴时。当右索引小于左索引时,找不到枢轴。在这种情况下,返回-1。当高点和低点指向相同的元素时,低点的元素是枢轴,并且该元素被返回。
if (high < low)
     return -1;
if (high == low)
     return low;
  • 除此之外,另一个基本情况是mid((low + high)/ 2)是关键点。当中间元素小于下一个元素或大于前一个元素时,将考虑该元素。
if (mid < high && arr[mid + 1] < arr[mid])
    reutrn mid;
if (mid > low && arr[mid] < arr[mid - 1])
    return mid - 1;
  • 递归案例:当没有一个基本案例满足时,则必须决定是否忽略前半部分或后半部分。通过检查第一个索引(低)处的元素是否大于中间索引处的元素来做出此决定。如果是的话,那么可以肯定的是,枢轴位于上半部分。否则,枢轴位于下半部分。
if (arr[low] > arr[mid]) 
    return findPivot(arr, low, mid - 1);    
else 
    return findPivot(arr, mid + 1, high);
  • 找到枢轴后,然后从枢轴遍历数组的左侧并检查是否所有元素都以降序排列,或者遍历数组的右侧并检查所有元素是否都以升序排列。

下面是上述方法的实现:

C++
#include 
 
using namespace std;
 
// Function to return the
// index of the pivot
int findPivot(int arr[], int low, int high)
{
    // Base cases
    if (high < low)
        return -1;
    if (high == low)
        return low;
 
    int mid = (low + high) / 2;
    if (mid < high && arr[mid + 1] < arr[mid])
    {
        return mid;
    }
 
    // Check if element at (mid - 1) is pivot
    // Consider the cases like {4, 5, 1, 2, 3}
    if (mid > low && arr[mid] < arr[mid - 1])
    {
        return mid - 1;
    }
 
    // Decide whether we need to go to
    // the left half or the right half
    if (arr[low] > arr[mid])
    {
        return findPivot(arr, low, mid - 1);
    }
    else
    {
        return findPivot(arr, mid + 1, high);
    }
}
 
// Function to check if a given array
// is sorted rotated or not
bool isRotated(int arr[], int n)
{
    int l = 0;
    int r = n - 1;
    int pivot = -1;
    if (arr[l] > arr[r])
    {
        pivot = findPivot(arr, l, r);
        int temp=pivot;
        // To check if the elements to the left
        // of the pivot are in descending or not
        if (l < pivot)
        {
            while (pivot > l)
            {
                if (arr[pivot] < arr[pivot - 1])
                {
                    return false;
                }
                pivot--;
            }
        }
 
        // To check if the elements to the right
        // of the pivot are in ascending or not
        pivot=temp;
        if(pivot < r) {
            pivot++;
            while (pivot < r) {
                if (arr[pivot] > arr[pivot + 1]) {
                    return false;
                }
                pivot++;
            }
        }
 
        // If both of the above if is true
        // Then the array is sorted rotated
        return true;
    }
 
    // Else the array is not sorted rotated
    else {
        return false;
    }
}
 
// Driver code
int main()
{
    int arr[] = { 4, 5, 1, 3, 2 };
    if (isRotated(arr, 5)) cout<<"true";
    else
    cout<<"false";
    return 0;
}
 
// This code is contributed by mohit kumar 29


Java
// Java implementation of the above approach
 
class GFG {
 
    // Function to return the
    // index of the pivot
    static int findPivot(int arr[], int low, int high)
    {
        // Base cases
        if (high < low)
            return -1;
        if (high == low)
            return low;
 
        int mid = (low + high) / 2;
        if (mid < high && arr[mid + 1] < arr[mid]) {
            return mid;
        }
 
        // Check if element at (mid - 1) is pivot
        // Consider the cases like {4, 5, 1, 2, 3}
        if (mid > low && arr[mid] < arr[mid - 1]) {
            return mid - 1;
        }
 
        // Decide whether we need to go to
        // the left half or the right half
        if (arr[low] > arr[mid]) {
            return findPivot(arr, low, mid - 1);
        }
        else {
            return findPivot(arr, mid + 1, high);
        }
    }
 
    // Function to check if a given array
    // is sorted rotated or not
    public static boolean isRotated(int arr[], int n)
    {
        int l = 0;
        int r = n - 1;
        int pivot = -1;
        if (arr[l] > arr[r]) {
            pivot = findPivot(arr, l, r);
            int temp=pivot;
            // To check if the elements to the left
            // of the pivot are in descending or not
            if (l < pivot) {
                while (pivot > l) {
                    if (arr[pivot] < arr[pivot - 1]) {
                        return false;
                    }
                    pivot--;
                }
            }
 
            // To check if the elements to the right
            // of the pivot are in ascending or not
           
            pivot=temp;
            else {
                pivot++;
                while (pivot < r) {
                    if (arr[pivot] > arr[pivot + 1]) {
                        return false;
                    }
                    pivot++;
                }
            }
 
            // If any of the above if or else is true
            // Then the array is sorted rotated
            return true;
        }
 
        // Else the array is not sorted rotated
        else {
            return false;
        }
    }
 
    // Driver code
    public static void main(String[] args)
    {
        int arr[] = {  4, 5, 1, 3, 2 };
        System.out.println(isRotated(arr, 5));
    }
}


Python3
# Python3 implementation of the above approach
 
# Function to return the
# index of the pivot
def findPivot(arr, low, high) :
 
    # Base cases
    if (high < low) :
        return -1;
         
    if (high == low) :
        return low;
 
    mid = (low + high) // 2;
    if (mid < high and arr[mid + 1] < arr[mid]) :
     
        return mid;
 
    # Check if element at (mid - 1) is pivot
    # Consider the cases like {4, 5, 1, 2, 3}
    if (mid > low and arr[mid] < arr[mid - 1]) :
     
        return mid - 1;
     
    # Decide whether we need to go to
    # the left half or the right half
    if (arr[low] > arr[mid]) :
     
        return findPivot(arr, low, mid - 1);
     
    else :
     
        return findPivot(arr, mid + 1, high);
     
# Function to check if a given array
# is sorted rotated or not
def isRotated(arr, n) :
 
    l = 0;
    r = n - 1;
    pivot = -1;
    if (arr[l] > arr[r]) :
     
        pivot = findPivot(arr, l, r);
        temp = pivot
        # To check if the elements to the left
        # of the pivot are in descending or not
         
        if (l < pivot) :
         
            while (pivot > l) :
             
                if (arr[pivot] < arr[pivot - 1]) :
                 
                    return False;
                 
                pivot -= 1;
 
        # To check if the elements to the right
        # of the pivot are in ascending or not
         
        else :
            pivot=temp
            pivot += 1;
            while (pivot < r) :
                if (arr[pivot] > arr[pivot + 1]) :
                    return False;
                 
                pivot ++ 1;
     
        # If any of the above if or else is true
        # Then the array is sorted rotated
        return True;
 
    # Else the array is not sorted rotated
    else :
        return False;
 
 
# Driver code
if __name__ == "__main__" :
 
    arr = [ 3, 4, 5, 1, 2 ];
    if (isRotated(arr, 5)) :
        print("True");
    else :
        print("False");
 
# This code is contributed by Yash_R


C#
// C# implementation of the above approach
using System;
 
class GFG {
  
    // Function to return the
    // index of the pivot
    static int findPivot(int []arr, int low, int high)
    {
        // Base cases
        if (high < low)
            return -1;
        if (high == low)
            return low;
  
        int mid = (low + high) / 2;
        if (mid < high && arr[mid + 1] < arr[mid]) {
            return mid;
        }
  
        // Check if element at (mid - 1) is pivot
        // Consider the cases like {4, 5, 1, 2, 3}
        if (mid > low && arr[mid] < arr[mid - 1]) {
            return mid - 1;
        }
  
        // Decide whether we need to go to
        // the left half or the right half
        if (arr[low] > arr[mid]) {
            return findPivot(arr, low, mid - 1);
        }
        else {
            return findPivot(arr, mid + 1, high);
        }
    }
  
    // Function to check if a given array
    // is sorted rotated or not
    public static bool isRotated(int []arr, int n)
    {
        int l = 0;
        int r = n - 1;
        int pivot = -1;
        if (arr[l] > arr[r]) {
            pivot = findPivot(arr, l, r);
            int temp = pivot;
            // To check if the elements to the left
            // of the pivot are in descending or not
            if (l < pivot) {
                while (pivot > l) {
                    if (arr[pivot] < arr[pivot - 1]) {
                        return false;
                    }
                    pivot--;
                }
            }
  
            // To check if the elements to the right
            // of the pivot are in ascending or not
            pivot=temp;
            else {
                pivot++;
                while (pivot < r) {
                    if (arr[pivot] > arr[pivot + 1]) {
                        return false;
                    }
                    pivot++;
                }
            }
  
            // If any of the above if or else is true
            // Then the array is sorted rotated
            return true;
        }
  
        // Else the array is not sorted rotated
        else {
            return false;
        }
    }
  
    // Driver code
    public static void Main(String[] args)
    {
        int []arr = { 3, 4, 5, 1, 2 };
        Console.WriteLine(isRotated(arr, 5));
    }
}
 
// This code contributed by Rajput-Ji


输出:
true



时间复杂度: O(N)为:

  • 使用O(log N)中的Binary Search查找枢轴元素
  • 但是为了检查左部分或右部分是降序还是升序,在最坏的情况下需要O(N)时间。
  • 因此,总体时间复杂度为O(N)