文章目录
一、Arrays.binarySearch()方法使用
Arrays.binarySearch()方法与其名字一样,是一个二分查找的方法。
通过二分法查找已排序数组,并返回其下标。
方法参数及其返回值如下:
当元素存在于数组中,则返回对应元素下标
import java.util.Arrays;
public class test1 {
public static void main(String[] args) {
int[] sort = new int[]{10,20,30,40,50,60};
int index = Arrays.binarySearch(sort,20);
System.out.println("20的下标为:"+index);
}
}
运行结果:20的下标为:1
当存在元素且存在多个
public class test1 {
public static void main(String[] args) {
//多个20
int[] sort = new int[]{10,20,20,40,50,60};
int index = Arrays.binarySearch(sort,20);
System.out.println("20的下标为:"+index);
//多个10
sort = new int[]{10,10,20,40,50,60};
index = Arrays.binarySearch(sort,10);
System.out.println("10的下标为:"+index);
}
}
运行结果:
20的下标为:2
10的下标为:0
为什么查找20与查找10返回的下标一个是后面的,一个是前面的呢?
我只能说与二分查找特性相关,待会放源码时再细说。
当元素不存在数组中
public class test1 {
public static void main(String[] args) {
int[] sort = new int[]{10,20,30,40,50,60};
int index = Arrays.binarySearch(sort,25);
System.out.println("25的下标为:"+index);
index = Arrays.binarySearch(sort,65);
System.out.println("65的下标为:"+index);
index = Arrays.binarySearch(sort,-2);
System.out.println("-2的下标为:"+index);
}
}
运行结果:
25的下标为:-3
65的下标为:-7
-2的下标为:-1
当不存在时,因20的下标为1,那么25的下标就为2,返回值为 -(2+1)也就是 -3.
而数组中最小值为10下标为0,而-2比10还小,那么下标就为0,返回值 -(0+1) 也就是-1.
为什么?待会细说
二、源码分析
Arrays.binarySearch()方法的两种传参:
//两个参数
public static int binarySearch(int[] a, int key) {
return binarySearch0(a, 0, a.length, key);
}
//四个参数
public static int binarySearch(int[] a, int fromIndex, int toIndex,int key) {
rangeCheck(a.length, fromIndex, toIndex);
return binarySearch0(a, fromIndex, toIndex, key);
}
我们可以看到到最后都会调用binarySearch0(a, fromIndex, toIndex, key)方法。
那我们先不看这个,我们先看**rangeCheck()**里面是怎样的
private static void rangeCheck(int arrayLength, int fromIndex, int toIndex) {
if (fromIndex > toIndex) {
throw new IllegalArgumentException(
"fromIndex(" + fromIndex + ") > toIndex(" + toIndex + ")");
}
if (fromIndex < 0) {
throw new ArrayIndexOutOfBoundsException(fromIndex);
}
if (toIndex > arrayLength) {
throw new ArrayIndexOutOfBoundsException(toIndex);
}
}
我们可以看到哈,这就只是一个防止越界的方法,那么关键代码还是在binarySearch0()中:
private static int binarySearch0(int[] a, int fromIndex, int toIndex,int key) {
int low = fromIndex;
int high = toIndex - 1;
while (low <= high) {
int mid = (low + high) >>> 1;
int midVal = a[mid];
if (midVal < key)
low = mid + 1;
else if (midVal > key)
high = mid - 1;
else
return mid; // key found
}
return -(low + 1); // key not found.
}
在这里我们可以看到这就是一个二分查找的流程,但是在返回上有点不同
当存在元素时,返回下标mid,不存在则返回 -(low+1)
而现在解决第一个问题,当出现重复元素时会取哪个下标
我们先来看图:
![](https://img-blog.csdnimg.cn/img_convert/07485b87505950dc943c82853db047fd.png)
![](https://img-blog.csdnimg.cn/img_convert/78d81b92086af496da756605301a0f86.png)
从图中我们可以得知:
当数组长度为偶数时,下标为偶数且靠近当前区间中间的元素会优先被查找
当数组长度为奇数时,下标为奇数且靠近当前区间中间的元素会优先被查找
再来看一组测试:
public static void main(String[] args) {
System.out.println("当前数组长度为奇数时:");
int[] sort = new int[]{10,10,30,40,50,60,70};
int index = Arrays.binarySearch(sort,10);
System.out.println("10的下标为:"+index);
sort = new int[]{10,20,20,40,50,60,70};
index = Arrays.binarySearch(sort,20);
System.out.println("20的下标为:"+index);
sort = new int[]{10,20,30,30,50,60,70};
index = Arrays.binarySearch(sort,30);
System.out.println("30的下标为:"+index);
sort = new int[]{10,20,30,40,40,60,70};
index = Arrays.binarySearch(sort,40);
System.out.println("40的下标为:"+index);
sort = new int[]{10,20,30,40,50,50,70};
index = Arrays.binarySearch(sort,50);
System.out.println("50的下标为:"+index);
sort = new int[]{10,20,30,40,40,60,60};
index = Arrays.binarySearch(sort,60);
System.out.println("60的下标为:"+index);
System.out.println("--------------");
System.out.println("当前数组长度为偶数时:");
sort = new int[]{10,10,30,40,50,60};
index = Arrays.binarySearch(sort,10);
System.out.println("10的下标为:"+index);
sort = new int[]{10,20,20,40,50,60};
index = Arrays.binarySearch(sort,20);
System.out.println("20的下标为:"+index);
sort = new int[]{10,20,30,30,50,60};
index = Arrays.binarySearch(sort,30);
System.out.println("30的下标为:"+index);
sort = new int[]{10,20,30,40,40,60};
index = Arrays.binarySearch(sort,40);
System.out.println("40的下标为:"+index);
sort = new int[]{10,20,30,40,50,50};
index = Arrays.binarySearch(sort,50);
System.out.println("50的下标为:"+index);
}
运行结果:
当前数组长度为奇数时:
10的下标为:1
20的下标为:1
30的下标为:3
40的下标为:3
50的下标为:5
60的下标为:5
.------------------
当前数组长度为偶数时:
10的下标为:0
20的下标为:2
30的下标为:2
40的下标为:4
50的下标为:4
现在我们可以得出结论,
当数组长度为奇数时,数组中有重复元素,Arrays.binarySearch()会优先返回奇数且靠近当前区间中间的下标
当数组长度为偶数时,数组中有重复元素,Arrays.binarySearch()会优先返回偶数且靠近当前区间中间的下标
现在来解决第二个问题,当元素不存在时如何返回下标:
从源码中我们可以知道,当元素不存在时的返回值与low有关:
当要查找的元素比数组中所有的值都小时:
low一直都会是0,直到mid=low且key<sort[mid] ==> hight=mid-1
从而low>hight导致跳出循环,输出结果。
当要查找的元素比数组中所有的值都大时:
right一直都会是0,直到mid=hight且key>sort[mid] ==> low=mid+1
从而low>hight导致跳出循环,输出结果。
当要查找的元素在数组范围内,但不存在时:
例如:
{10,20,30,40,50,60} 查找 ->25
①mid = 2 , sort[mid] = 30 > 25 ==> hight = mid-1. (此时low=0,hight=1)
②mid = 0 , sort[mid] = 10 < 25 ==> low = mid+1 (此时low=1,hight=1)
③mid = 1 , sort[mid] = 20 < 25 ==> low = mid+1 (此时low=2,hight=1 跳出循环)
④返回 -(low+1) 也就是 -(2+1) = -3.
附上用到此方法的算法题:
剑指 Offer II 008. 和大于等于 target 的最短子数组
个人拙见,如有错误,麻烦请指出,谢谢