先决条件:检查是否使用线性搜索对数组进行了排序和旋转
给定N个不同整数的数组arr [] ,任务是检查逆时针旋转时此数组是否已排序。已排序的数组不被视为已排序和旋转,即应该至少旋转一圈。
例子:
Input: arr[] = { 3, 4, 5, 1, 2 }
Output: true
Explanation:
Sorted array: {1, 2, 3, 4, 5}.
Rotating this sorted array clockwise
by 3 positions, we get: { 3, 4, 5, 1, 2}
Input: arr[] = {7, 9, 11, 12, 5}
Output: true
Input: arr[] = {1, 2, 3}
Output: false
方法:本文已经讨论了使用线性搜索解决此问题的一种方法。
在本文中,提到了一种使用二进制搜索概念的方法。
- 要应用二进制搜索,数组需要遵循某种顺序,通过该顺序,每次迭代都可以消除数组的一半。
- 因此,对数组进行排序和旋转后的数组的顺序是,枢轴左侧的所有元素(阵列旋转的点)都按降序排列,而枢轴右侧的所有元素都将按降序排列升序排列。
可以从下面的插图中看到:
- 因此,可以通过以下方式使用二进制搜索和递归来找到枢轴:
- 基本案例:基本案例将是在找到枢轴时或在给定数组中找不到枢轴时。当右索引小于左索引时,找不到枢轴。在这种情况下,返回-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)