所谓双调查找 : 就是在一个数组中的所有元素是先递增后递减的,则这个数组被称为双调的。
以a数组为例 :{1,2,3,5,8,9,6,4,-1,-9};
基本思想:
1. 既然是有序的,自然想到的是二分搜索
2. 但是与普通的二分搜索不一样,不知道拐点在何处
3. 所以大致分为三种情况:
① a[mid] 在 左半边但未越过拐点
②a[mid] 在右半边越过了拐点
③a[mid]刚好在拐点
所以可以分为以上三种情况进行递归查找
public static int specialBinarySearch(int [] a,int start,int end,int target) { //a数组为先递增后递减
if(start <= end) {
int mid = start + (end - start) / 2;
if(a[mid] == target)
return mid;
int status = -1;
status = checkStatus(a,start,end); //判断中位数是以上哪种情况
if(a[mid] > target) {
if(status == 3) {
// 在a[mid] > target中,如果是第三种情况,
//只需要将左半边正常二分查找(升序),右半边正常二分查找(降序)即可
int index = -1;
index = binarySearchAscend(a,start,mid-1,target); //二分查找(升序)
if(index != -1)
return index;
return binarySearchDescend(a,mid+1,end,target);//二分查找(降序)
}
else if(status == 2) {
//在a[mid] > target中,如果是第二种情况,
//只需要将左半边特殊二分查找,右半边正常二分查找(降序)即可
int index = -1;
index = specialBinarySearch(a,start,mid-1,target);
if(index != -1)
return index;
return binarySearchDescend(a,mid+1,end,target);
}
else if(status == 1) {
//在a[mid] > target中,如果是第一种情况,
//只需要将左半边正常二分查找(升序),右半边特殊二分查找即可
int index = -1;
index = binarySearchAscend(a,start,mid-1,target);
if(index != -1)
return index;
return specialBinarySearch(a,mid+1,end,target);
}
else
return -1;
}
else {
if(status == 3)
//在a[mid] < target中,如果是第三种情况,
//要查找的元素比最大值还要大,说明该数组没有要查找的元素,return -1即可
return -1;
else if(status == 2)
//在a[mid] < target中,如果是第二种情况
//只需要将左半边特殊二分查找即可
return specialBinarySearch(a,start,mid-1,target);
else if(status == 1)
//在a[mid] < target中,如果是第一种情况
//只需要将右半边特殊二分查找即可
return specialBinarySearch(a,mid+1,end,target);
else
return -1;
}
}
return -1;
}
//判断中位数情况
public static int checkStatus(int [] a,int start,int end) {
int index = start + (end - start) / 2;
if(a[index-1] < a[index] && a[index] > a[index+1])
return 3;
else if(a[index-1] > a[index] && a[index] > a[index+1])
return 2;
else if(a[index-1] < a[index] && a[index] <a[index+1])
return 1;
else
return -1;
}
//二分查找(升序)
public static int binarySearchAscend(int [] a,int start,int end,int target) {
if(start <= end) {
int mid = start + (end - start) / 2;
if(a[mid] == target)
return mid;
else if(a[mid] > target)
return binarySearchAscend(a,start,mid-1,target);
return binarySearchAscend(a,mid+1,end,target);
}
return -1;
}
//二分查找降序
public static int binarySearchDescend(int [] a,int start,int end,int target) {
if(start <= end) {
int mid = start + (end - start) / 2;
if(a[mid] == target)
return mid;
else if(a[mid] > target)
return binarySearchDescend(a,mid+1,end,target);
return binarySearchDescend(a,start,mid-1,target);
}
return -1;
}