/*题目要求时间复杂度只能是O(logn),所以只需考虑如何二分
按照某个点旋转 其实按照left mid right的增减关系能够确定旋转点在哪个分区
这就可以先logn时间找到旋转的点的位置centre
第二次找索引只需要在旋转位置centre的基础上对索引进行取mod即可*/
class Solution {
public:
int search(vector<int>& nums, int target) {
int centre;
int left , mid , right;
int len = nums.size();
left = 0;
right = len - 1;
while(left < right){//二分寻找有序数列的旋转位置
mid = (left + right)/2;
if(nums[mid] >= nums[left]){//左区递增
if(nums[mid] > nums[mid + 1]) {centre = mid + 1;break;}
else left = mid + 1;
}
else if(nums[mid] <= nums[right]){//右区递增
if(nums[mid] < nums[mid - 1]) {centre = mid;break;}
else right = mid - 1;
}
}
if(nums[0] < nums[len - 1])//递增序列 绕空点旋转 特殊的边界情况
centre = 0;
left = 0;
right = nums.size() - 1;
while(left <= right){//第二次二分找到target的位置
if(left == right){
if(nums[(left + centre)%len] == target) return (left + centre) % len;
else return -1;
}
mid = (right + left)/2;
if(nums[(mid + centre)%len] > target) right = mid - 1;
else if(nums[(mid + centre)%len] < target) left = mid + 1;
else return (mid + centre)%len;
}
return -1;
}
};