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.
solution: 方法一是先找pivot位置,然后二分查找前半或者后半部分;
方法二就是直接改进二分查找,找到该值。
方法一如下: 需要两次二分查找。写完之后看别人的blog发现一个问题,int mid = start + (end - start)/2;应该这么写,而不是原来这样,防止溢出,需注意。
class Solution {
public:
int searchPivot(int A[], int start, int end)
{
int mid = (end + start) / 2;
if(A[start] < A[end]) //no roated
return -1;
else if( (start+1) == end )
return start;
if(A[start] > A[mid])
return searchPivot(A, start, mid);
else if(A[mid] > A[end])
return searchPivot(A, mid, end);
}
int binarySearch(int A[], int start, int end, int target)
{
//int mid = (end + start)/2;
if(start > end)
return -1;
while(start <= end)
{
int mid = (end + start) / 2;
if(A[mid] == target)
return mid;
else if(A[mid] > target)
end = mid-1;
else
start = mid+1;
}
return -1;
}
int search(int A[], int n, int target) {
// Note: The Solution object is instantiated only once and is reused by each test case.
if(n <= 0 || A == NULL)
return -1;
int find = -1;
int start = 0;
int end = n-1;
int pivot = searchPivot(A, start, end);
if(pivot == -1)
{
find = binarySearch(A, start, end, target);
return find;
}
if(target >= A[start])
find = binarySearch(A, start, pivot, target);
else if(target <= A[end])
find = binarySearch(A, pivot+1, end, target);
return find;
}
};
方法二:循环中先判断是左边有序还是右边有序,根据mid值和start,end比较:
若左边有序,继续判断,若数在左边有序数列中,end = mid -1;反之start= mid+1;
若右边有序,判断,若数在有序的右边,start = mid+1;反之end = mid -1;
class Solution {
public:
int search(int A[], int n, int target) {
// Note: The Solution object is instantiated only once and is reused by each test case.
if(n <= 0 || A == NULL)
return -1;
int start = 0;
int end = n-1;
while( start <= end )
{
//int mid = (end + start)/2; // to avoid overflow use
int mid = start + (end - start)/2;
if(A[mid] == target)
return mid;
if(A[start] <= A[mid])
{
if( target >= A[start] && target < A[mid])
end = mid -1;
else
start = mid+1;
}
else
{
if( target > A[mid] && target <= A[end])
start = mid + 1;
else
end = mid - 1;
}
}
return -1;
}
};