LEETCODE算法注解33:
假设按照升序排序的数组在预先未知的某个点上进行了旋转。
( 例如,数组 [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
解法:很明显,最初的思路时通过先找出旋转点,再做判断,去哪一部分中查找,还是直接顺序查找,两者的复杂度相同的都是O(n),不符合条件。题目要求
logn很明显是要求二分查找。此时已经与旋转点没有关系了,因为你查找旋转点的复杂度都为O(n)了。
我们要从旋转点发现新的规律:
旋转过后,将数组从中间分开,一半是必然有序的,另一半不确定。
如4 7 8 0 1 2 3已经旋转后得到,数组的下表[0~6], 4,7,8,0是无序的,1,2,3是有序的。target=7,我们发现7不属于有序的123,则target应该再4,7,8,0中寻找。查找过程与上面一样。这就是递归。
class Solution {
public int search(int[] nums, int target) {
//leetcode一般都须判断空
if(nums.length==0) return -1;
return ans(nums,target,0,nums.length-1);
}
public int ans(int[] nums, int target, int start, int end)
{
int mid = (start + end) / 2;
if(nums[mid] == target) return mid;
if(start <= end)
{
//考虑到start可能等于mid也算作有序因此<=
if(nums[start]<=nums[mid])
{
if(target>=nums[start] && target<=nums[mid])
{
return ans(nums,target,start,mid-1);
}
else
{
return ans(nums,target,mid+1,end);
}
}
else
{
if(target>=nums[mid] && target<=nums[end])
{
return ans(nums,target,mid+1,end);
}
else
{
return ans(nums,target,start,mid-1);
}
}
}
return -1;
}
}