二分查詢及其擴充套件
阿新 • • 發佈:2018-11-19
#二分查詢及其擴充套件#
- 二分查詢法
- 時間複雜度
- O(logn)
- 實現
- 遞迴
- 時間複雜度
public int binarySearchV2(int[] a,int low,int high,int value) { if(low>high) return -1; while (low<=high){ int mid = (low+high)/2; if(a[mid] == value){ return mid; }else if(a[mid] > value){ return binarySearchV2(a,low,high-1,value); }else { return binarySearchV2(a,mid+1,high,value); } } return -1; }
- **非遞迴**
public int binarySearchV1(int[] a,int n,int value){ int low = 0; int high = n-1; while(low<=high){ int mid = (low+high)/2; if(a[mid] == value){ return mid; }else if(a[mid]>value){ high = mid - 1; }else{ low = mid+1; } } return -1; }
- 注意點
- 退出迴圈的條件是low <= high
- (low+high)容易溢位 改為 low+(high-low)/2 ==> >>1
- low 和 high的更新
- 擴充套件
- 順序訪問及查詢
- 基於陣列
- 資料量太大不適合,資料量太小也不適合
- 相關變形題目
- 查詢第一個值等於給定值的元素
- 查詢最後一個值等於給定值的元素
- 查詢第一個大於等於給定值的元素
- 查詢最後一個小於等於給定值的元素
- 分析
- 以上幾個都是二分查詢的變形題目,需要學會舉一反三,相信大部分人一看程式碼馬上就能懂了
/**
* 獲取第一個等於給定值的值
* */
public static int getFisrtEquals(int[] a,int n,int value){
int low = 0;
int high = n-1;
while(low <= high){
int mid = low + ((high-low)>>1);
if(a[mid] >value){
high = mid-1;
}else if(a[mid] <value){
low = mid+1;
}else {
// 如果mid已經到陣列第一位肯定是第一個等於value 或者mid=value且前一位不等於value
if(mid ==0 || a[mid-1] != value) return mid;
// 否則高位等於mid-1,相當於往前移一位
else high = mid-1;
}
}
return -1;
}
/**
* 獲取最後一個等於給定值的
*/
public static int getLastEquals(int[] a,int n,int value){
int low = 0;
int high = n-1;
while(low <= high){
int mid = low + ((high-low)>>1);
if(a[mid] >value){
high = mid -1;
}else if(a[mid]<value){
low = mid+1;
}else{
if(mid == n-1 || a[mid+1]!=value) return mid;
else low = mid+1;
}
}
return -1;
}
/**
* 獲取第一個大於等於給定值的
*/
public static int getFirstMoreThanEquals(int[] a,int n,int value){
int low = 0;
int high = n-1;
while(low <= high){
int mid = low + ((high-low)>>1);
if(a[mid]<value){
low = mid+1;
}else{
if(mid==0 || a[mid-1]<value){
return mid;
}else {
high = mid - 1;
}
}
}
return -1;
}
/**
* 最後一個小於等於給定值的
*/
public static int getLastSmallerEquals(int[] a,int n ,int value){
int low = 0;
int high = n-1;
while(low <= high){
int mid = low + ((high-low)>>1);
if(a[mid]>value){
high = mid-1;
}else{
// 應該就比較好理解了
if(mid==n || a[mid+1]>value) return mid;
else low=mid+1;
}
}
return -1;
}
- 想要寫出一個 bug free的二分查詢也不容易,需要考慮 迴圈的終止條件,區間的上下界值的選擇以及返回值的選擇