二分查詢總結
二分查詢法作為一種常見的查詢方法,將原本是線性時間提公升到了對數時間範圍,大大縮短了搜尋時間,但它有乙個前提,就是必須在有序資料中進行查詢。二分查詢很好寫,卻很難寫對,據統計只有10%的程式設計師可以寫出沒有bug的的二分查詢**。出錯原因主要集中在判定條件和邊界值的選擇上,很容易就會導致越界或者死迴圈的情況。
下面對二分查詢及其變形進行總結:
1 最基本的二分查詢
public int
binarysearch
(int
a,int target,
int n)
else
if(a[mid]
> target)
else
}return-1
;}
其中,有幾個要注意的點:
迴圈的判定條件是:low <= high
為了防止數值溢位,mid = low + (high - low)/2
當a[mid]
不等於target
時,high = mid - 1
或low = mid + 1
2. 查詢目標值區域的左邊界/查詢與目標值相等的第乙個位置/查詢第乙個不小於目標值數的位置
a = [1,3,3,5, 7 ,7,7,7,8,14,14]target = 7
return 4
public int
binarysearchlowerbound
(int
a,int target,
int n)
else}if
(low < a.length && a[low]
== target)
return low;
else
return-1
;}
3. 查詢目標值區域的右邊界/查詢與目標值相等的最後乙個位置/查詢最後乙個不大於目標值數的位置
a = [1,3,3,5,7,7,7, 7 ,8,14,14]target = 7
return 7
public int
binarysearchupperbound
(int
a,int target,
int n)
else}if
(high >=
0&& a[high]
== target)
return high;
else
return-1
;}
此題以可變形為查詢第乙個大於目標值的數/查詢比目標值大但是最接近目標值的數
,我們已經找到了最後乙個不大於目標值的數,那麼再往後進一位,返回high + 1
,就是第乙個大於目標值的數。
4. 查詢最後乙個小於目標值的數/查詢比目標值小但是最接近目標值的數
此題以可由第 2 題變形而來,我們已經找到了目標值區域的下(左)邊界,那麼再往左退一位,即low - 1
,就是最後乙個小於目標值的數。其實low - 1也是退出迴圈後high的值,因為此時high
剛好等於low - 1
,它小於low
,所以while
迴圈結束。我們只要判斷high
是否超出邊界即可。
a = [1,3,3, 5 ,7,7,7,7,8,14,14]target = 7
return 3
int low =
0, high = n, mid;
while
(low <= high)
else
}return high <0?
-1: high;
5. 查詢第乙個大於目標值的數/查詢比目標值大但是最接近目標值的數
此題以可由第 3 題變形而來,我們已經找到了目標值區域的上(右)邊界,那麼再往右進一位,即high + 1
,就是第乙個大於目標值的數。其實high + 1
也是退出迴圈後low
的值,因為此時low
剛好等於high + 1
,它大於high,所以while
迴圈結束。我們只要判斷low
是否超出邊界即可。
a = [1,3,3,5,7,7,7,7, 8 ,14,14]target = 7
return 8
int low =
0, high = n, mid;
while
(low <= high)
else
}return low > n ?-1
: low;
6. 旋轉陣列返回最小元素
6.1 查詢旋轉陣列的最小元素(假設不存在重複數字)
input: [3,4,5,1,2]output: 1
public int
findmin
(int
nums)
}return nums[left]
;}
注意這裡和之前的二分查詢的幾點區別:
迴圈判定條件為left < right
,沒有等於號
迴圈中,通過比較nums[left]
與num[mid]
的值來判斷mid
所在的位置:
如果nums[mid]
>nums[right]
,說明前半部分是有序的,最小值在後半部分,令left = mid + 1
;
如果nums[mid] <= num[right]
,說明最小值在前半部分,令right = mid
。
最後,left
會指向最小值元素所在的位置。
6.2 查詢旋轉陣列的最小元素(存在重複項)
input: [2,2,2,0,1]output: 0
public int
findmin
(int
nums)
return nums[left]
;}
和之前不存在重複項的差別是:當nums[mid] == nums[right]
時,我們不能確定最小值在mid
的左邊還是右邊,所以我們就讓右邊界減一。 二分查詢小結
本文主要總結二分查詢相關問題,這裡 其實已經有乙個不錯的總結了。跟著那裡的題目列表,自己寫寫答案。anyway,還得實操 二分查詢相關問題總結如下 問題整理參考 這裡 給定乙個有序陣列 非降序 陣列array和目標值target,陣列中可能有重複元素 尋找任意i使得array i 等於target,...
二分查詢小結
int binary find vector a,int target 查詢等於目標的數的位置 else return 1 int binary find1 vector a,int target 查詢第乙個不小於目標的數的位置,作用同stl中的lower bound else return rig...
演算法訓練之二分查詢小結(C )
從這週的習題和每日一題來看,二分查詢雖然思想簡單,但變體眾多,且極易出錯。因此,小結以求避坑。參考 王爭老師的專欄 二分查詢 上 二分查詢 下 先給出二分查詢模板 c int low 0 int high n 1 while low high else if a mid value else 其中,...