不知道未经过转动的原数组是升序排列还是降序排列的情况下,我们可以先按升序二分查找,再按降序二分查找。
/**
* 二分查找,数组不存在重复项
* 当前数组肯定是有两部分是有序的,所以取mid时,
* 要么 [l, mid] 是有序的,要么 [mid + 1, r]是有序的
*
* @param A int整型一维数组
* @param target int整型
* @return int整型
*/
public int search (int[] A, int target) {
// write code here
int len = A.length;
if(len == 0) return -1;
int l = 0, r = len - 1;
// 假设数组按升序排列,进行二分查找
while (l <= r){
int mid = (l + r) / 2;
if(A[mid] == target)
return mid;
/*
l 到 mid 是升序的
反证法:
假设 l 到 mid 不是升序的,那么数组肯定有转动,
且转动后原数组的末尾值落在 l 到 mid 之间,那么必有 tmp 属于 [l, mid],
使得 A[tmp] < A[l], 此时 l 到 tmp - 1 是升序的,tmp 到 mid 是升序的,
又由于原数组是升序的,转动后必有 l 到 tmp - 1 的元素都大于 tmp 到 mid 的
元素,则 A[l] > A[mid],与条件相反。
*/
if(A[mid] >= A[l]){
// target可能在 A[mid] 左边
if(A[l] <= target && A[mid] > target)
r = mid - 1;
// target不可能在 A[l] 左边
else
l = mid + 1;
}
// mid右侧(包括mid)都是升序的
else {
if(A[r] >= target && A[mid] < target)
l = mid + 1;
else
r = mid - 1;
}
}
l = 0;
r = len - 1;
// 假设数组按降序排列,进行二分查找
while (l <= r){
int mid = (l + r) / 2;
if(A[mid] == target)
return mid;
// l 到 mid 是降序的
if(A[mid] <= A[l]){
// target可能在 A[mid] 左边
if(A[l] >= target && A[mid] < target)
r = mid - 1;
// target不可能在 A[mid] 左边
else
l = mid + 1;
}
// mid右侧(包括mid)是降序的
else {
if(A[r] <= target && A[mid] > target)
l = mid + 1;
else
r = mid - 1;
}
}
return -1;
}