思路:(好像剑指offer也有这一题)
1.这种题直接搜索肯定会超时。所以考点肯定是二分法。
2.旋转数组有什么特点呢?我个人觉得就是最开头的数,比它小的数字肯定在尾部。
知识点复习
首先要懂二分法基本写法:(我从网上抄的,只强调一点:mid应该用减法来计算,防止溢出)
int binarySearch(int[] nums, int target) {
int left = 0;
int right = nums.length - 1;
while(left <= right) {
int mid = (right + left) / 2;
if(nums[mid] == target)
return mid;
else if (nums[mid] < target)
left = mid + 1;
else if (nums[mid] > target)
right = mid - 1;
}
return -1;
}
然后也没什么了,基本思路都写在注释里了,注意下细节就行(断点:两截序列的交叉)
代码如下:
class Solution {
public int search(int[] nums, int target) {
if(nums==null || nums.length==0){
return -1;
}
if(nums.length==1) return target==nums[0]?0:-1;
return dfs(nums,0,nums.length-1,target);
}
private int dfs(int[] nums,int left,int right,int target) {
if(left > right) {
return -1;
}
int mid = (left+right)/2;
if(target == nums[mid]) {
return mid;
}
//左半边是升序,断点在右边
if(nums[mid]>nums[left]) {
if(target<nums[left]) {
//只可能去右半边查找
return dfs(nums,mid+1,right,target);
}else if(target == nums[left]){
return left;
}else if(target>nums[left]){
//这里不可能等于,之前已经判断了。
if(target>nums[mid]) {
//去右半边查找
return dfs(nums,mid+1,right,target);
}else {
return dfs(nums,left,mid-1,target);
}
}
} else if(nums[mid]<nums[left]) {
// 断点在左边
if(target>nums[left]) {
//只可能去左半边查找
return dfs(nums,left,mid-1,target);
}else if(target == nums[left]){
return left;
}else if(target<nums[left]){
if(target>nums[mid]) {
// 右边
return dfs(nums,mid+1,right,target);
}else {
// 左边
return dfs(nums,left,mid-1,target);
}
}
}else if(nums[mid] == nums[left]){
//mid == left
if(nums[left] == target) return left;
if(nums[right] == target) return right;
}
return -1;
}
}