演算法 二分查詢小結

2021-09-22 22:50:08 字數 3652 閱讀 1544

二分查詢總結

二分查詢法作為一種常見的查詢方法,將原本是線性時間提公升到了對數時間範圍,大大縮短了搜尋時間,但它有乙個前提,就是必須在有序資料中進行查詢。

二分查詢很好寫,卻很難寫對,據統計只有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)/2a[mid]不等於target時,high = mid - 1low = 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 其中,...