二分搜索就是在搜索东西时每次都从中间下手,一次排除一半,快速锁定目标。
所以能用二分搜索的数据,都是按一定大小规律排列的
基础版:
java
public class BinarySearch {
// 二分查找基础版
public static int binarySearchBasic(int[] a,int target) {
int i =0,j=a.length-1;//设置指针和初值
while (i<=j){//范围内有东西
int m = (i+j)/2;
if(target < a[m]){//目标在左边
j = m-1;
} else if (target > a[m]) {//目标在右边边
i = m+1;
}else {//找到了
return m;
}
}
return -1;
}
}
while循环中用<=而不用<号的原因:因为在两个指针重合时,即:i=j,会直接返回-1。如此数据在这种情况就查不出来了
不用等号的原因也与a.length-1有关
int m = (i+j)/2;可能遇到的问题:在数字太大的情况下会导致溢出变成负数。所以可以改为>>>1符号
改动版:
java
// 二分查找改动版
public static int binarySearchAlternative(int[] a,int target) {
int i =0,j=a.length; //第一处
while (i<j){ //第二处
int m = (i+j)>>>1;
if(target < a[m]){
j = m; //第三处
} else if (a[m] < target) {
i = m+1;
}else {
return m;
}
}
return -1;
}
平衡版:
java
// 二分查找均衡版
public static int binarySearchBalance(int[] a,int target) {
int i =0,j=a.length;
while (1<j-i){
int m = (i+j)>>>1;
if(target < a[m]){
j = m;
} else if{
i = m;
}
}
if(a[i] == target){
return i;
}else {
return -1;
}
}
}
优点:减少循环内的平均比较次数(在数据量大时才能体现到)
java中的二分查找:
java
public static int binarySearch(int[] a, int key) {
return binarySearch0(a, 0, a.length, key);
}
/**
* Searches a range of
* the specified array of ints for the specified value using the
* binary search algorithm.
* The range must be sorted (as
* by the {@link #sort(int[], int, int)} method)
* prior to making this call. If it
* is not sorted, the results are undefined. If the range contains
* multiple elements with the specified value, there is no guarantee which
* one will be found.
*
* @param a the array to be searched
* @param fromIndex the index of the first element (inclusive) to be
* searched
* @param toIndex the index of the last element (exclusive) to be searched
* @param key the value to be searched for
* @return index of the search key, if it is contained in the array
* within the specified range;
* otherwise, <code>(-(<i>insertion point</i>) - 1)</code>. 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 in the range greater than the key,
* or {@code toIndex} if all
* elements in the range 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.
* @throws IllegalArgumentException
* if {@code fromIndex > toIndex}
* @throws ArrayIndexOutOfBoundsException
* if {@code fromIndex < 0 or toIndex > a.length}
* @since 1.6
*/
public static int binarySearch(int[] a, int fromIndex, int toIndex,
int key) {
rangeCheck(a.length, fromIndex, toIndex);
return binarySearch0(a, fromIndex, toIndex, key);
}
// Like public version, but without range checks.
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.
}
low是插入点
最后return -(low + 1);的意思是找不到这个数,但是可以在这个索引插入数据
java中0与-0是一个数
java
//验证类
int[] a ={2,5,8};
int target =4;
int i = Arrays.binarySearch(a,target);
System.out.println(i);
if(i<0){
int insertIndex = Nath.abs(i + 1);
int [] b = new int[a.length + 1];
System.arraycopy(a,0,b,insertIndex);
b[insertIndex] = target;
System.arraycopy(a,insertIndex,b,insertIndex+1,a.length-insertIndex);
System.out.println(Arrays.toString(b));
}
//这样可以把没有检索到的数据添加上去
Leftmost:
java
public static int binarySearchLeftMost(int[] a,int target) {
int i =0,j=a.length-1;
int candidate = -1;
while (i<=j){
int m = (i+j)>>>1;
if(target < a[m]){
j = m-1;
} else if (a[m] < target) {
i = m+1;
}else{
//记录候选位置
candate = m;
j=m - 1;
}
}
return candidate;
}
}
寻找重复元素中最靠左的元素
rigntmost:
java
public static int binarySearchLeftMost(int[] a,int target) {
int i =0,j=a.length-1;
int candidate = -1;
while (i<=j){
int m = (i+j)>>>1;
if(target < a[m]){
j = m-1;
} else if (a[m] < target) {
i = m+1;
}else{
//记录候选位置
candate = m;
j=m - 1;
}
}
return candidate;
}
}
与Leftmost代码类似,只不过是寻找重复元素中最靠右的元素