题目描述:
假设按照升序排序的数组在预先未知的某个点上进行了旋转。
( 例如,数组 [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
解题思路如下:
首先考虑数组的长度是否为0,如果为0,输出-1.否则使用二分查找法查找存在的目标值,并返回它的索引。
在编写的二分查找的函数中,首先要确保最低位(low)小于最高位(high)。否则就不满足二分查找的条件则输出-1。接着计算中间值,如果中间值等于目标值,则直接输出下标。如果不等于在分以下两种情况进行讨论:
1.如果最低位小于等于中间位,则判断目标值是否同时在最低位(low)和中间值(middle)之间,如果满足条件采用二分查找的基本思想进行递归,用最低位和中间值-1进行查找目标值。否则用该二分查找函数的最低位和最高位分别选为middle+1和最高位。
2.如果最低位大于中间位,则判断目标值是否同时在中间位(middle)和最高位之间,如果满足条件则继续用middle+1和high进行查找。否则用low和middle-1继续查找。
Java代码如下:
class Solution {
public int search(int[] nums, int target) {
int n=nums.length;
if(n== 0){
return -1;
}
return binarySearch(nums,target,0,n-1);
}
//运用二分查找的方法查找目标数值的下标 基本方式就是二分查找的方式
public int binarySearch(int[] nums,int target,int low,int high){
if(low > high){
return -1;
}
int middle = low+(high-low)/2;
//如果中间值等于目标值,输出下标
if(nums[middle] == target){
return middle;
}
//如果是最低位小于中间值的情况
if(nums[low]<=nums[middle]){
//考虑最低位等于目标值的情况
if(nums[low]<= target && target < nums[middle]){
//运用递归的方法
return binarySearch(nums,target,low,middle-1);
}
return binarySearch(nums,target,middle+1,high);
}else{
//要考虑到目标值等于最高位的情况
if(nums[middle]< target && target <= nums[high]){
return binarySearch(nums,target,middle+1,high);
}
return binarySearch(nums,target,low,middle-1);
}
}
}
注意:为什么要在nums[low]<= target && target < nums[middle]写小于等于,是因为在这个条件中需考虑到最低位等于目标值的情况。即在最低位等于目标值的情况下,可以用二分法继续查找。