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

📅  最后修改于: 2021-09-03 03:58:59             🧑  作者: Mango

先决条件:检查数组是否使用线性搜索进行排序和旋转
给定一个由 N 个不同整数组成的数组arr[] ,任务是检查这个数组在逆时针旋转时是否排序。排序后的数组不被认为是排序和旋转的,即至少应该有一次旋转。
例子:

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

  • 为了应用二分搜索,数组需要遵循某种顺序,在每次迭代时,可以消除数组的一半。
  • 因此,排序和旋转数组的数组所遵循的顺序是枢轴左侧的所有元素(数组旋转的点)按降序排列,枢轴右侧的所有元素将按升序排列。
    这可以从下图看出:

  • 因此,可以通过以下方式使用二进制搜索和递归找到枢轴:
    • 基本情况:基本情况将是在找到枢轴时或在给定数组中找不到枢轴时。当右索引小于左索引时,无法找到枢轴。在这些情况下返回 -1。当 high 和 low 指向同一个元素时,low 处的元素是枢轴并返回该元素。
if (high < low)
     return -1;
if (high == low)
     return low;
  • 除此之外,另一个基本情况是 mid((low + high) / 2) 是一个支点。当该元素小于下一个元素或大于前一个元素时,将考虑位于 mid 的元素。
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


Javascript


输出:
true

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

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

如果您想与行业专家一起参加直播课程,请参阅Geeks Classes Live