二分查找是一種很是經典的查找算法,其應用場景也很是多,算法思路清晰,可是其效率很高。算法
/** * 二分查找 * 若是數組中存在目標值,返回其對應下標 * 若是數組中不存在目標值,則返回-1 * */ public static int binarySearch(int[] arr,int target){ int low = 0; int high = arr.length-1; while (low<=high){ int mid = low+(high-low)/2; if(target<arr[mid]){ high = mid-1; } else if(target>arr[mid]){ low = mid+1; } else{ return mid; } } return -1; }
注意點:時間複雜度爲O(logN),計算mid有兩種方式,1) mid=(low+high)/2,2) mid=low+(high-low)/2,low+high有可能出現加法溢出,最好用第二種方式。3) 循環條件有兩種方式,low<high和low<=high,若是是low<high,那麼相應的high的賦值表達式就是high=mid,若是是low<=high,相應的high的賦值表達式就是high=mid-1。數組
應用一:求開方spa
求一個數num的算術平方根sqrt,一個數num的算術平方根sqrt必定在0~num/2之間,而且知足sqrt=num/sqrt,能夠利用二分查找在0~num/2之間查找sqrt。code
public static int mysqrt(int x){
if (x<=1){
return x;
}
int low=1;
int high=x/2;
while (low<=high){
int mid=low+(high-low)/2;
int sqrt=x/mid;
if (sqrt<mid){
high=mid-1;
}
else if(sqrt>mid){
low=mid+1;
}
else{
return mid;
}
}
return high;
}
應用二:擺硬幣blog
給定n個硬幣,在第i行擺i個硬幣,求總共能夠擺滿多少行,能夠利用二分查找。element
public static int arrangeCoins(int n) { int low = 0; int high = n; while(low <= high){ int mid = low + (high - low) / 2; long x = mid * (mid + 1L) / 2; if(x == n){ return mid; } else if(x < n){ low = mid + 1; } else high = mid - 1; } return high; }
應用三:有序數組的 single elementget
在一個有序數組中只有一個元素出現一次,其他元素均出現2次,找出這個元素,能夠利用二分查找。class
public static int singleNoDuplicate(int[] arr){ int low=0; int high=arr.length-1; while (low<high){ int mid = low+(high-low)/2; if (mid%2==1){ mid--; } if(arr[mid]==arr[mid+1]){ low=mid+2; } else{ high=mid; } } return arr[low]; }