QUESTION:
假设按照升序排序的数组在预先未知的某个点上进行了旋转。
( 例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] )。
搜索一个给定的目标值,如果数组中存在这个目标值,则返回它的索引,否则返回 -1 。
你可以假设数组中不存在重复的元素。
你的算法时间复杂度必须是 O(log n) 级别。
示例 1:
输入: nums = [4,5,6,7,0,1,2], target = 0 输出: 4 示例 2:
输入: nums = [4,5,6,7,0,1,2], target = 3 输出: -1
EXPLANATION:
首先我们看到时间复杂度是logn,那么就说明肯定是二分法了。确定了二分法,那么难点其实就出在了怎么样确定分法。普通的二分法其实就是确定target和mid值的对比来确定在左还是右的区间,那么我们有没有办法也同样使用mid值来确定呢。答案是可以的。首先,mid值如果大于start值,那么就说明左半边是递增的,否则就说明右半边是递增的。其次再确定target值在不在递增的这一边,如果不在,就说明在另外一边。经过这样的循环就能最后确定target值在哪一边了。这样就可以替代之前用mid的方式,其实还是使用了二分法的思想。
思路:
1.确定start和end
2.确认mid是否大于等于start,说明左边是正序的
2.1.左边正序的情况下判断target在不在左边(通过target,start,还有mid的值来确定)左边就将mid赋值给end
3.mid小于start说明右边是正序
3.1.右边是正序那判断target在不在右边,同样通过target,mid,end来进行判断,在右边就将start赋值给mid
4.循环结束后就是最后的结果
SOLUTION:
class Solution {
public int search(int[] nums, int target) {
int start = 0;
int end = nums.length-1;
int mid;
while (start<=end){
mid = (start+end)/2;
if(nums[mid] == target) return mid;
if(nums[mid]>=nums[start]){
if (nums[start] <= target && nums[mid] > target) end = mid - 1;
else start = mid + 1;
}else{
if(nums[mid]<target && nums[end]>=target) start = mid+1;
else end = mid-1;
}
}
return -1;
}
}