Это можно сделать в O(logN)
с помощью слегка измененного двоичного поиска.
Интересное свойство отсортированного + повернутого массива состоит в том, что при его делении на две половины, по крайней мере, одна из двух половин будетвсегда сортировать.
Let input array arr = [4,5,6,7,8,9,1,2,3]
number of elements = 9
mid index = (0+8)/2 = 4
[4,5,6,7,8,9,1,2,3]
^
left mid right
, как кажется, правый подмассив не сортируется, а левый подмассив сортируется.
Если середина оказывается точкой поворота, то и левая, и праваяпод-массивы будут отсортированы.
[6,7,8,9,1,2,3,4,5]
^
Но в в любом случае одна половина (подмассив) должна быть отсортирована .
Мы можем легко узнать, какая половина отсортированасравнивая начальный и конечный элементы каждой половины.
Как только мы находим, какая половина отсортирована, мы можем видеть, присутствует ли ключ в этой половине - простое сравнение с крайностями.
Если ключприсутствует в той половине, мы рекурсивно вызываем функцию в этой половине
, иначе мы рекурсивно вызываем наш поиск в другой половине.
Мы отбрасываем одну половину массива в каждом вызове, что делает этот алгоритм O(logN)
.
Псевдокод:
function search( arr[], key, low, high)
mid = (low + high) / 2
// key not present
if(low > high)
return -1
// key found
if(arr[mid] == key)
return mid
// if left half is sorted.
if(arr[low] <= arr[mid])
// if key is present in left half.
if (arr[low] <= key && arr[mid] >= key)
return search(arr,key,low,mid-1)
// if key is not present in left half..search right half.
else
return search(arr,key,mid+1,high)
end-if
// if right half is sorted.
else
// if key is present in right half.
if(arr[mid] <= key && arr[high] >= key)
return search(arr,key,mid+1,high)
// if key is not present in right half..search in left half.
else
return search(arr,key,low,mid-1)
end-if
end-if
end-function
Ключевым моментом здесь является то, что один подмассив всегда будет отсортирован, с помощью которого мы можем отбросить половину массива.