binarySearch的妙用

介绍

数组工具类Arrays有个很神奇的方法:binarySearch

它有很多重载,我们介绍一个。

/**
     * Searches the specified array of ints for the specified value using the
     * binary search algorithm.  The array must be sorted (as
     * by the {@link #sort(int[])} method) prior to making this call.  If it
     * is not sorted, the results are undefined.  If the array contains
     * multiple elements with the specified value, there is no guarantee which
     * one will be found.
     *
     * @param a the array to be searched
     * @param key the value to be searched for
     * @return index of the search key, if it is contained in the array;
     *         otherwise, <tt>(-(<i>insertion point</i>) - 1)</tt>.  The
     *         <i>insertion point</i> is defined as the point at which the
     *         key would be inserted into the array: the index of the first
     *         element greater than the key, or <tt>a.length</tt> if all
     *         elements in the array are less than the specified key.  Note
     *         that this guarantees that the return value will be &gt;= 0 if
     *         and only if the key is found.
     */
    public static int binarySearch(int[] a, int key) {
        return binarySearch0(a, 0, a.length, key);
    }

作用:寻找特定元素在一个数组中的下标。

要求:数组必须有序。

返回值:

  • 如果数组中有该元素,则返回它的下标
  • 如果数组中不含有该元素,则返回它的插入点的负值减一

测试

   int myarr[] = new int[]{1, 3, 4, 6, 8, 9};
        int indexOf1 = Arrays.binarySearch(myarr, 1);
        int indexOf6 = Arrays.binarySearch(myarr, 6);
        int indexOf9 = Arrays.binarySearch(myarr, 9);
        System.out.println("index of 1: " + indexOf1);
        System.out.println("index of 6: " + indexOf6);
        System.out.println("index of 9: " + indexOf9);

1,6,9显然是在数组中的,所以结果都是大于等于0的。

index of 1: 0
index of 6: 3
index of 9: 5

再看:

 int myarr[] = new int[]{1, 3, 4, 6, 8, 9};
        int indexOf2 = Arrays.binarySearch(myarr, 2);
        int indexOf7 = Arrays.binarySearch(myarr, 7);
        int indexOf10 = Arrays.binarySearch(myarr, 10);
        int indexOfNegative5 = Arrays.binarySearch(myarr, -5);
        System.out.println("index of 2: " + indexOf2);
        System.out.println("index of 7: " + indexOf7);
        System.out.println("index of 10: " + indexOf10);
        System.out.println("index of -5: " + indexOfNegative5);

2,7,10,-5全部都不在数组中,此时的结果是:

index of 2: -2
index of 7: -5
index of 10: -7
index of -5: -1

我们借此理解一下插入点的负值减一


比如2。

它的插入点的下标是1。

于是插入点的负值就是-1。

于是插入点的负值减一就是-2。


比如10。

它的插入点的下标是6。

于是插入点的负值就是-6。

于是插入点的负值减一就是-7。


比如-5。

它的插入点的下标是0。

于是插入点的负值就是-0。

于是插入点的负值减一就是-1。


特点

比如有一个数组myarr

我想插入新的元素newNum,则int i= Arrays.binarySearch(myarr,newNum)

  • 如果i大于0,则表示它在原数组中已经存在。
  • 如果i等于0,则表示它就是原来数组最小的值。
  • 如果i是负数,则表示它在原数组中不存在。
  • 如果i等于-1,则表示它比原数组中所有的值都要小。

newNum是原数组中不存在的数,那么-(i+1)就是它要在原数组中插入的位置。

在我插入元素的时候,这些特点就可以用上。


应用

问题:

我随机生成大量数据(随机数),如果找到它们中最大的五个?

这里的大量指的是亿级别的。所以千万不能用排序。能用的就是能够快速查找的binarySearch

代码:

public class TestBinarySearch {
    public static void main(String[] args) {
        int[] arr = new int[5];
        Random random = new Random();
        for(int i = 0; i < 1000000000; i++) {
            //随机生成一个均匀分布的整数
            int num = random.nextInt();
            //调用binarySearch以找到num在arr中应该插入的位置
            int index = Arrays.binarySearch(arr, num);

            //如果num是最小的,跳过
            if(index == 0 || index == -1) continue;

            //如果是未出现的数
            //-(index+1)就是新的数需要插入的位置
            if(index < 0)index = -(index+1);

            //让index位置之前的数都往前挪一位
            for(int j = 1; j < index; j++) {
                arr[j - 1] = arr[j];
            }
            //把num放进去
            arr[index - 1] = num;
        }

        System.out.println(Arrays.toString(arr));
    }
}

我这里是一边生成数,一边插入。你也可以先生成好大量数据,然后遍历,对于其中的每个数,都用binarySearch检验,原理是一样的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章