1、在有序数组中确定num存在还是不存在:
public static boolean exist(int[] arr,int num){ if (arr==null || arr.length==0){ return false; } int l=0,r=arr.length-1,m=0; while (l<=r){ m=l+((r-l)>>2);//等同于(l+r)/2,这样子做的目的是为了防止溢出!当数组非常长的时候,l跟r加起来可能 会导致数据溢出! if(arr[m]==num){ return true;//说明该num存在 }else if (arr[m]>num){ r=m-1; }else { l=m+1; } } return false; } //判断中点与num的大小,如果相等则直接返回表示找到num,不等则看大小关系,中点值大于num改变右边界,小于num改变左边界,继续二分查找!直到找到,或者 退出循环,没有找到返回false。
2.在有序数组中找>=num的最左位置:
public static int findleft(int[]arr,int num){ int l=0,r=arr.length-1,m=0; int ans=-1; while (l<=r){ m = l+(r-l)/2; if (arr[m]>=num){ ans=m; r=m-1; }else{ l=m+1; } } return ans; } //从中点值先开始判断,因为是有序数组,当中点值大于num的时候,则表明中点值右边的所有值都是大于num的,这个时候就只需要改变右边界,从中点值的左边继续找即可,如果中点值小于num则说明中点+1,到右边界的范围中可能存在>=num的值,改变左边界,继续二分判断即可!
3.在有序数组中找<=num的最右位置:
public static int fineRight(int[]arr int num){ int l=0,r=arr.length-1,m=0; int ans=-1; while (l<=r){ m=l+(r-l)/2; if (arr[m]<=num){ ans=m; l=m+1; }else{ r=m-1; } } }
4.二分搜索不一定发生在有序数组上(比如寻找峰值问题!力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台162. 寻找峰值)
public static int findPeakElement(int[]arr){
int n=arr.length;
if (arr.length==1){
return 0;
}
if (arr[0]>arr[1]){
return 0;
}//判断第一个值是不是峰值,如果是直接返回对应下标
if (arr[n-1]>arr[n-1]){
return n-1;
}//判断最后一个值是不是峰值,如果是直接返回对应下标
int l=1,r=n-2,m=0;//当第一个和最后一个值都不是峰值的时候,则有一个趋势,第一个值是上升趋势,最后一个值是下降趋势,则从第二个值开始,到倒数第二个值间,至少存在一个峰值。
int ans=-1; //找到中点值与旁边两个值的大小关系来判断接下来从那个区域进行二分
while (l<=r){
m=l+(r-l)/2;
if (arr[m]<arr[m-1]){//当中点值小于临左边的值时,可以知道在左边界到中点-1的范围内是至少存在一个峰值的,让右边界等于中点-1,继续二分。
r=m-1;
}else if (arr[m]<arr[m+1]){//同理当中点值小于临右边的值时,可以知道在中点+1到右边界的范围内是至少存在一个峰值的,让左边界等于中点-1,继续二分。
l=m+1;
}else{
ans=m;//中点值即大于右边值也大于左边值,此时中点值为峰值,记录下标,退出循环。
break;
}
}
return ans;
}
二分搜索不一定就是要数组有序,也可以通过两侧有没有来进行二分!