题目描述
- 有序数组中搜索值,显然用二分
- 旋转带来的影响并不大,只要多加几个判断,改改范围就行。
思路 & 代码
- 首先找出两部分升序子数组的分割点k
- 然后再判断需要在哪个子数组进行二分,并进行二分即可。
- 注意二分时候一定要舍去已判断无效值(也就是half)
更新。。之前的方法实际上不满足O(logn),分割点查找应该也使用二分查找。
class Solution {
public int search(int[] nums, int target) {
// 思路:一次分割点查找O(logn)。两次二分查找O(logn)
int k = -1, low = 0, top = nums.length - 1;
while(low <= top){
k = (low + top) / 2;
// 找到的情况:注意长度为1时,需要进行k + 1 == nums.length判断
if(k + 1 == nums.length || nums[k] > nums[k + 1]){
break;
}
if(nums[k] < nums[0]){
top = k - 1;
}
else{
low = k + 1;
}
}
// 判断选择在哪个部分进行二分
if(target > nums[nums.length-1] || k == nums.length-1){
return binary(nums,0,k,target);
}
else{
return binary(nums,k+1,nums.length-1,target);
}
}
public int binary(int[] nums,int left,int right,int target){
// l = 0,r = -1的情况也要考虑
if(left >= right){
if(target == nums[left]){
return left;
}
return -1;
}
int half = (left+right)/2;
// 相等判断
if(target == nums[half]){
return half;
}
// 缩短范围,+-1去掉已判断的half
else if(target > nums[half]){
return binary(nums,half+1,right,target);
}
else{
return binary(nums,left,half-1,target);
}
}
}