先决条件:检查数组是否使用线性搜索进行排序和旋转
给定一个由 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。当 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