设按照升序排序的数组在预先未知的某个点上进行了旋转。
( 例如,数组 [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
注意代码中的各个return。
错误解法:
不通过的用例:
输入: [3,5,1] 3
输出: -1
预期: 0
class Solution {
//二分法,取中间位置值,和最右边的元素比较,若小于,则较大的部分在左边,否则在右边
public int search(int[] nums, int target) {
if(nums.length == 0)
return -1;
return search_helper(nums, 0, nums.length-1, target);
}
public int search_helper(int[] nums,int l, int r,int target){
if(l>r)
return -1;
int mid = (l+r)/2;
if(target == nums[mid])
return mid;
else if(target > nums[mid]){
if(nums[mid] < nums[r])
return search_helper(nums, mid+1, r, target);
else
return search_helper(nums, l, mid-1, target);
}
else{
if(nums[mid] < nums[r])
return search_helper(nums, l, mid-1, target);
else
return search_helper(nums, mid+1, r, target);
}
}
}
可以看出上面的分类是有问题的,最后转化思路:
1.先找出发生旋转的元素,比如456012找0,351找1。从后往前遍历元素,发现i-1位置的元素值上升,i元素即为目标值。
2.假设遍历结束后未找到i值,即为正常的二分查找;
3.遍历结束后找到i值,此时我们就得到了整个数组的最大值nums[i-1],和最小值nums[i](题目里说过旋转前是升序的->,则旋转后的数组为两个部分升序->->)
4.分组时当元素大于最小值小于最大值,都直接返回-1。否则,当其>=nums[0]时,我们要在区间[0,i-1]寻找;当其<=nums[n],我们要在区间[i+1,n]寻找
成功
执行用时 : 1 ms, 在Search in Rotated Sorted Array的Java提交中击败了99.69% 的用户
内存消耗 : 35 MB, 在Search in Rotated Sorted Array的Java提交中击败了92.18% 的用户
class Solution {
public int search(int[] nums, int target) {
if(nums.length == 0)
return -1;
int n = nums.length-1;
int i;
for(i=n;i>0;i--){
if(nums[i-1]>nums[i])
break;
}
//此时的i记为旋转发生的位置
if(i==0)
//未旋转
return search_helper(nums, 0, n, target);
else{
if(target == nums[i])
return i;
if(target > nums[i-1] || target < nums[i])//大于整个序列的最大值,小于整个序列的最小值
return -1;
else if(target <= nums[n])
return search_helper(nums, i+1, n, target);
else if(target >= nums[0] )
return search_helper(nums, 0, i-1, target);
}
return -1;
}
public int search_helper(int[] nums,int l, int r,int target){
if(l>r)
return -1;
int mid = (l+r)/2;
if(target == nums[mid])
return mid;
else if(target > nums[mid])
return search_helper(nums, mid+1, r, target);
else
return search_helper(nums, l, mid-1, target);
}
}