介紹
數組工具類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 >= 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
檢驗,原理是一樣的。