注意: 以下算法的实现,是在数组都是升序的情况下讨论的
public static void main(String[] args) {
int [] arr1=new int[]{1,3,21,45,67,77,89,90};
int target=22;
int i = binarySearch(arr1,target);
System.out.println(target+"的位置是:"+i);
int [] arr2=new int[]{45,67,77,89,90,1,3,21,45};
target=67;
i=rotatedBinarySearch(arr2,target);
System.out.println(target+"的位置是:"+i);
}
/**
* 对于一个升序数组,使用循环在目标数组中查找
* @param arr 查找的目标数组
* @param target 目标值
* @return 返回target在arr中的目标位置,-1为不存在
*/
public static int binarySearch(int[] arr, int target){
int start=0,end=arr.length-1;
//使用小于等于才能完成最后一次的比较
while (start<=end){
//采用这样的计算方式,来避免数据过大的溢出问题
int mid=start+(end-start)/2;
if(arr[mid]==target){
return mid;
}else if(arr[mid]<target){
//目标值大于中位值
start=mid+1;
}else {
//目标值大于中位值
end=mid-1;
}
}
return -1;
}
/**
* 对于仅有一个旋转点的升序数组,使用二分法查找
* @param arr 旋转升序数组
* @param target 目标值
* @return 返回target在arr中的目标位置,-1为不存在
*
* 思路:
* 判断目标值与中位数是否相等
* 判断中位数与旋转点的位置(通过mid和start位置的值比较可得到)
* 如果中位数大于等于start位置的值,证明旋转点在中位数右侧
* 如果start位置的值<target值<mid位置的值
* 修改end位置
* 如果中位数小于start位置的值,证明旋转点在中位数左侧
* 如果mid位置的值<target值<end位置值
* 修改start位置
*/
public static int rotatedBinarySearch(int[] arr,int target){
int start=0,end=arr.length-1;
while (start<=end){
int mid=start+(end-start)/2;
if(arr[mid]==target){
return mid;
}else if(arr[mid]>=arr[start]){
//旋转点在中位数右侧
if(arr[start]<=target&& target<arr[mid]){
end=mid-1;
}else {
start=mid+1;
}
}else {
//旋转点在中位数左侧
if(arr[mid]<target && target<=arr[end]){
start=mid+1;
}else {
end=mid-1;
}
}
}
return -1;
}