题意:Suppose a sorted array is rotated at some pivot unknown to you beforehand.
(i.e., 0 1 2 4 5 6 7 might become 4 5 6 7 0 1 2).
You are given a target value to search. If found in the array return its index, otherwise return -1.
You may assume no duplicate exists in the array.
思路:原始的在有序数组寻找target元素的方法就是采用二分查找。这道题的不同在于将有序数组在一个未知位置进行了旋转,所以不能简单的按照原始方法来寻找。
如果有序数组进行了反转,则数组的最后一个元素小于数组的第二个元素,并且在数组的中间某个位置的其后一个元素的值将小于当前元素的值。在找准旋转的位置,我们可以在这两段中进行二分查找。
class Solution {
public:
int search(vector<int>& nums, int target) {
if(nums.empty()) return -1;
int n=nums.size()-1;
if(nums[0]<nums[n]) //数组未进行旋转,在整个数组的范围内进行二分查找
{
int low=0;
int high=n;
int middle=0;
while(low<=high){
middle=(low+high)/2;
if(nums[middle]==target) return middle;
else if(nums[middle]<target){
low=middle+1;
}
else high=middle-1;
}
return -1;
}
//数组进行了旋转,首先找出中间的分界点j,将数组分成[0~j-1],[j-n]两部分再进行二分查找
else{
int i=-1;
int j=0;
while(nums[++i]<=nums[++j]);//在找出中间nums[i]>nums[j]的位置
//target不在[0~j-1]范围内
if(target<nums[0]){
int low=j;
int high=n;
int middle=0;
while(low<=high){
middle=(low+high)/2;
if(nums[middle]==target) return middle;
else if(nums[middle]<target){
low=middle+1;
}
else high=middle-1;
}
return -1;
}
//target不在[j~n]范围内
else{
int low=0;
int high=i;
int middle=0;
while(low<=high){
middle=(low+high)/2;
if(nums[middle]==target) return middle;
else if(nums[middle]<target){
low=middle+1;
}
else high=middle-1;
}
return -1;
}
}
}
};
这种方法思路正确,AC。后来,笔者又在网上找到了更好的方法,这里贴出代码,学习一下。
public class Solution {
public int search(int[] A, int target) {
int l = 0;
int r = A.length - 1;
//直接按照二分查找
while (l <= r) {
int mid = (l + r) / 2;
if (target == A[mid]) return mid;
//三种可能有序的情况(一定有一种成立),选择有序的情况进行二分查找
//[l~r]是有序的
if (A[l] <= A[r]) {
if (target < A[mid]) r = mid - 1;
else l = mid + 1;
} else if (A[l] <= A[mid]) { //[l~mid]是有序的
if (target > A[mid] || target < A[l]) l = mid + 1;
else r = mid - 1;
} else { //[mid+1~r]是有序的
if (target < A[mid] || target > A[r]) r = mid - 1;
else l = mid + 1;
}
}
return -1;
}
}