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檢驗,原理是一樣的。

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