对于二分法最容易混淆的点在边界的确定和判断条件。
我们知道数组表示为[0,length),为左闭右开区间,用l表示数组的左边界,r表示数组的右边界,即[l,r);于是mid=(l+r)/2表示二分中点。
首先要想查找到值,则数组不能为空,于是有r>l+1,则二分循环条件应为while(r>l+1)。
其次对于循环中的判断条件,即arr[mid]和key的大小比较,有三种:
第一:arr[mid]=key,则直接返回
第二:arr[mid]>key,则取左区间继续查找,此时的mid不是我们要的结果,即此时的mid已经取不到了,则r=mid (注意:不是mid-1,因为这是左闭右开的区间,mid本来就取不到了!)
第三:arr[mid]<key,则取右区间继续查找,l=mid+1,此时的mid已取不到了
但是在这里,为了简化代码,我们用不着把arr[mid]=key的情况单独判断,当区间长度为1时,剩下的就是我们要的结果,于是我们把arr[mid]<=key两种情况结合一下,此时因为可以取mid了,所以l=mid
到这里,整个二分查找就完成了;
/**
* 折半查找
* @param arr:查找数组
* @param key:需查找的值
* @return l:查找值的下标
*/
private static int binarySearch(int[] arr,int key){
int l=0,r=arr.length,mid;
while(r>l+1){
mid=(l+r)/2;
if(arr[mid]<=key){ //取右区间
l=mid;
}else{
r=mid;
}
}
return l;
}