一、题目描述
升序排列的整数数组 nums 在预先未知的某个点上进行了旋转(例如, [0,1,2,4,5,6,7] 经旋转后可能变为 [4,5,6,7,0,1,2] )。
请你在数组中搜索 target ,如果数组中存在这个目标值,则返回它的索引,否则返回 -1 。
示例 1:
输入:nums = [4,5,6,7,0,1,2], target = 0
输出:4
示例 2:
输入:nums = [4,5,6,7,0,1,2], target = 3
输出:-1
示例 3:
输入:nums = [1], target = 0
输出:-1
提示:
1 <= nums.length <= 5000
-10^4 <= nums[i] <= 10^4
nums 中的每个值都 独一无二
nums 肯定会在某个点上旋转
-10^4 <= target <= 10^4
二、题解
方法一:使用两次二分查找
第一次二分查找,查找旋转位置
第二次二分查找,再在对应的区间查找目标值
class Solution {
public int search(int[] nums, int target) {
int n = nums.length;
int mid = binarySearch(nums,target);
if(n>=2&&mid == 0&&nums[0]<nums[1])
mid = n - 1;
if(target>=nums[0]){
return binarySearch(nums,target,0,mid);
}else{
return binarySearch(nums,target,mid + 1,n - 1);
}
}
public int binarySearch(int[] nums,int target){
int n = nums.length;
int left = 0;
int right = nums.length - 1;
while(left<right){
int mid = left + ((right - left)>>1);
if(mid+1<n&&nums[mid]>nums[mid+1])
return mid;
else if(nums[mid]>nums[left])
left = mid;
else
right = mid;
}
return 0;
}
public int binarySearch(int[] nums,int target,int left,int right){
while(left<=right){
int mid = left + ((right - left)>>2);
if(nums[mid]==target)
return mid;
else if(nums[mid]>target)
right = mid - 1;
else
left = mid + 1;
}
return -1;
}
}
方法二:使用一次二分查找
每次判断通过mid切割出来的两部分哪部分是有序的
class Solution {
public:
int search(vector<int>& nums, int target) {
int n = nums.size();
if(!n) return -1;
if(n==1) return nums[0] == target?0:-1;
int left = 0,right = n - 1;
while(left<=right){
int mid = left + ((right - left)>>1);
if(nums[mid] == target) return mid;
if(nums[0]<=nums[mid]){
if(target >= nums[0] && target < nums[mid])
right = mid - 1;
else
left = mid + 1;
}else{
if(target <= nums[n-1]&&target > nums[mid]){
left = mid + 1;
}else{
right = mid - 1;
}
}
}
return -1;
}
};