Есть целочисленный массив nums
, отсортированный в порядке возрастания (с различными значениями).
Nums
передаётся в вашу функцию, возможно, повёрнутым с неизвестным индексом поворота k
(1 <= k < nums.length
) так, чтобы результирующий массив был [nums[k], nums[k+1], …, nums[n-1], nums[0], nums[1], …, nums[k-1]] (0-индексированный).
Например, [0,1,2,4,5,6,7] может быть повернуто в индексом поворота 3 и стать [4,5,6,7,0,1,2].
Итак, дан массив nums
после возможного поворота и целочисленный target
Нужно вернить индекс target
, если он находится в nums
, или -1
, если он не находится в nums
.
Нужно написать алгоритм со сложностью времени выполнения O(log n)
.
Входные данные: nums = [4,5,6,7,0,1,2], target = 0
Результат: 4
Входные данные: nums = [4,5,6,7,0,1,2], target = 3
Результат: -1
Входные данные: nums = [1], target = 0
Результат: -1
class Solution {
public:
int search(vector<int>& nums, int target) {
int size = nums.size();
int s=0,e=size-1,m;
while(s <= e) {
m = s + (e-s)/2;
if(nums[m] == target) return m;
if( nums[s] <= nums[m] ) { // непрерывная последовательность слева?
// да
if(nums[s] == target) {
return s;
} else if(nums[s] < target && target < nums[m]) { // target в левой половине?
e = m - 1; // да, отсекаем правую половину
} else {
s = m + 1; // нет, отсекаем левую половину
}
} else {
// непрерывная последовательность справа
if(nums[e] == target) {
return e;
} else if(nums[m] < target && target < nums[e]) { // target в правой половине?
s = m + 1; // да, отсекаем левую половину
} else {
e = m - 1; // нет, отсекаем правую половину
}
}
}
return -1;
}
};
Для определения используется дихотомический поиск.
Определяется середина последовательности.
Определяется, какая из половин последовательности (левая или правая) является непрерывной (если начальное значение последовательности меньше серединной, то непрерывная последовательность слева)
Определяется, в какой половине находится target
.
Для непрерывной последовательности слева, target
будет в левой части, если значение target
находится между начальным значением и серединой.
Для непрерывной последовательности справа, target
будет в правой части, если значение target
находится между серединой и конечным значением.
Если target
находится в левой части, нужно отсечь правую и наоборот.