二分寫法總結

2021-08-21 10:40:32 字數 2483 閱讀 7188

二分答案

浮點數二分

首先二分的思想不難,問題在於整數二分的時候如果沒有處理好二分的區間,會導致死迴圈的情況,比如下面這種二分求上界的寫法

int

binarysearch

(int l,

int r)

return l;

}

這樣寫到最後二分的區間是[l, l+1),且如果check(l)返回的是true,那麼將會陷入死迴圈,因為這時候mid始終等於l。

其次二分應用的情況很多,對於每種情況,寫法也會不同,所以在這裡總結下對於各種情況二分的寫法

二分查詢也有很多情況,例如在有序陣列中找某乙個數(記為a)的位置,如果只有乙個數,那直接返回這個數的位置就好了,但是如果存在好幾個相同的該數字,二分又可以分為找第乙個出現的位置(即陣列中第乙個大於等於a的數的位置)或者最後乙個出現的位置(即第乙個大於a的數的位置的前一位),這兩種就是所謂的下界和上界,這兩種我們放到二分答案的情況裡說明

這裡我們先看每種數只有乙個的情況,假設a陣列元素嚴格遞增

int

binarysearch

(int

*a,int l,

int r,

int key)

//key是我們要找的數

return-1

;}

這就是最簡單的二分了,我們來具體看看它的計算過程

首先該寫法它的 l 和 r,即我們二分的區間的左右端點,它是保證要找的數在[l, r)裡的,也就是區間左端點可能是我們要找的數,而區間右端點不可能是

當區間中點mid偏小時,l = mid + 1,二分區間變成[mid + 1, r),如果該數字存在,必定還在該區間內;

如果mid偏大,r = mid,mid不可能是我們要找的數,而r端點本來就不會是答案,所以可以這麼寫

所以每次二分區間[l, r),區間必定會縮小,不可能死迴圈,最後一次判定時(如果一直沒找到該數),區間變成[l, l + 1),這時候mid = l,如果mid還不等於我們要找的數,區間就會縮小到 l == r ,便退出了迴圈,返回-1表示沒找到

雖然該寫法沒什麼大問題,而且比較簡潔,但是我們需要注意:

二分答案是資訊學競賽中一種常用的技巧,首先我們要搞明白什麼情況下可以二分答案

當我們的答案具有連續性,單調性的時候,我們就可以二分答案,那什麼叫答案具有連續性呢?即可能的答案區間 [l, r] 中,x假如可能是答案,那麼x - 1,x + 1可能也是答案;

什麼叫單調性呢?即當x越來越大,就會越來越難以/容易滿足題目要求

二分答案的過程往往會涉及到求答案的上、下界

所謂上下界,即假設我們二分的潛在答案區間為[l, r], 假設可行的答案區間為[l, r],那麼l就是下界,r就是上界,即答案區間的左右端點,往往分別對應著 最少/小 和 最多/大

當我們設定二分潛在的答案區間為左閉右開的時候,即 [l, r),最終得到的 l 就是答案的上界,因為這時候 l 的右側答案都已經不符合要求,l必定是答案中最大的了

int

upperbound

(int l,

int r)

return l;

}

迴圈結束後區間大小就是1,即 [l, l+1),最終答案就是l

但是這樣的寫法需要注意以下3點:

初始二分的潛在的答案區間的右端點r要設定成比最大可能答案大,因為r不會被訪問到

還是 l + r 可能溢位

如果題目說了可能沒有答案,最後需要檢查下 l,因為可能二分的區間裡沒有答案,每次迴圈都是 r = mid,最終的l沒有被檢查過

當我們設定二分潛在的答案區間為左開右閉的時候,即 (l, r],最終得到的 r 就是答案的下界,因為這時候 r 的左側答案都已經不符合要求,r必定是答案中最小的了

int

lowerbound

(int l,

int r)

return r;

}

同樣的我們也需要注意以下三點:

初始二分的潛在的答案區間的左端點l要設定成比最小可能答案大小,因為l不會被訪問到

還是 l + r 可能溢位

如果題目說了可能沒有答案,最後需要檢查下 r,因為可能二分的區間裡沒有答案,每次迴圈都是 l = mid,最終的r沒有被檢查過

浮點數二分基本不會有什麼問題,因為不會有整數二分取整沒取好導致死迴圈的問題

有兩種寫法:

以迴圈次數為迴圈終止條件

for

(int i =

0; i <60;

++i)

//迴圈60次就已經可以達到很高的精度了

以精度位迴圈終止條件

while

(r - l < eps)

//eps為題目要求的精度

比較推薦第一種寫法,因為第二種如果精度設定過小,加上浮點數的精度問題還是可能死迴圈

標準二分寫法

該寫法最大的優勢就是不必考慮返回left還是right,因為條件是while le題目 704.二分查詢 1 若中位數是左中位數,那麼判斷排除左半部的語句,一定要排除左中位數,不然兩個元素的時候,左中位數就是首元素,會死迴圈。樣例 class solution int le 0,ri siz 1 w...

二分查詢總結

今天上csdn,發現一篇關於二分查詢演算法的文章被置頂,回帖也相當熱烈。我覺得演算法總重要的還是要了解思想,至於程式設計技巧則是其次。二分查詢在計算中演算法中的重要性不言而喻,許多變形的演算法都是基於此演變的,比如二分查詢樹等。所以此演算法程式我也打算總結一下。當然經典的演算法討論莫過於jon be...

二分演算法總結

討論分為3種,第一種是搜尋佇列中任意我們需求的結果,第三種我們需求佇列中有多個返回第乙個,第四種未我們搜尋佇列中有多個返回最後乙個元素的index。第一種 在一行排好序佇列a中搜尋target,一定有。int binarysearch int a,int n,int target return 1 ...