此题来自于:LeetCode 33.搜索旋转排序数组/二分搜索
- 因为题目要求O(logn),且虽然旋转了(也有可能没旋转),但是还是部分有序的,采取二分搜索,但是关键在于目前的搜索区间[left,right)内,可能并不是有序的(因为旋转过了)。
所以只能分类:
-
当
mid > nums[left]
时说明目前mid在旋转过后的左段,当且仅当target < m && target >= nums[left]
时,往左边搜,其余往右边搜。 -
当
mid < nums[left]
时说明目前mid在旋转过后的右段,当且仅当target > m && target <= nums[right - 1]
,往右搜,其余情况往左搜。 -
为什么要比较mid和nums[left]?
-
因为能给target锁定范围,一比较,就知道left到mid是不是有序的了(或者说是否被旋转过)。
AC代码:
class Solution {
public:
vector<int> nums;
int target;
int search(vector<int>& nums, int target) {
this->nums = nums;
this->target = target;
int n = nums.size();
if(n == 0) return -1;
return binary_search(0,n);
}
int binary_search(int left,int right){ //二分法的搜索区间才是关键
while(left < right){
int mid = left + (right - left) / 2;
int m = nums[mid];
if(m == target) return mid;
else if(m > nums[left]){ //在左段
if(target < m && target >= nums[left]) right = mid;
else left = mid + 1;
}
else{ //在右段
if(target > m && target <= nums[right - 1]) left = mid + 1;
else right = mid;
}
}
return -1;
}
};