1. 程式人生 > >二分法詳解

二分法詳解

數據 經典的 最終 http 二分 體驗 循環 pad data

連續看我文章的朋友就會發現,我寫文章有一個特點,總是用經典的例題引出一個方法,在之後的文章中才會介紹這種方法的詳細信息。這樣做的好處是:避免了先接觸幹巴巴的概念導致很多朋友看的時候會有索然無味這種體驗,由具體題目的分析過程來一步一步優化,最終引出方法這種形式,更能讓這種方法變得順理成章,也更能讓讀者體會到方法的巧妙之處。這種由興趣激發的探索的欲望對徹底掌握一種方法其實是比較重要的。直接去接觸一種方法有可能目的只是學會,但是產生興趣而去探索一種方法的始末才能真正了解、掌握甚至讀懂其真正的奧秘所在。


下面,我將會給大家詳細的介紹二分法的信息。

二分法起源於數學中找函數零點的問題:

對於區間[a,b]上連續不斷且f(a)·f(b)<0的函數y=f(x),通過不斷地把函數f(x)的零點所在的區間一分為二,使區間的兩個端點逐步逼近零點,進而得到零點近似值的方法叫二分法。

技術分享

如圖所示,區間的端點為 A 點和 B 點,函數的圖像在區間 AB 範圍內是單調遞增的,現在要找函數圖像的零點 C 。由於這個圖像比較特殊,區間 AB 的中點正好是 C 點,所以只需要第一次判斷區間中心點就可以找到。假設 D 點是區間的中心,那麽可以看出 區間 AD之間的函數值全部小於零,因此全部不滿足條件,區間 DB中,函數連續且單調遞增,左半邊函數值小於零,右半邊函數值大於零,那麽在 DB 之間必然存在一個位置 使得函數值等於零。也就意味著以 D 點為分界,左半邊 一定沒有答案,右半邊一定有答案。這樣不斷縮小區間,不斷逼近,一定能讓包含答案的區間長度足夠小,比題目要求的精度還要小,這個時候,區間內的任意一個實數都可以作為答案。使用這種方法求函數零點的條件是:在區間範圍內,函數圖像連續且單調。

現在將這種二分的思想運用在程序設計中,也能產生神奇的效果。

之前在例題中,我使用二分法的情境是這樣的:由於 循環要進行 1e18 量級的次數,會超時,因此我在尋求一種方法,能夠減少循環執行的次數,這個時候題目隱含的條件是 天數和麻雀個數是在逐天增加,也就是題目所給的條件呈現出來的是線性的關系,在區間的中心位置取測試點,將區間一分為二,這時候必然能夠肯定有一個區間裏所有的數據均不滿足條件,而另一區間存在數據能夠達到條件。如此將區間不斷等分,每次都能巧妙減少一半的數據量,只在符合條件的區間中查找,效率非常高。(沒看過之前文章的朋友可能需要看過昨天的文章才能了解)

二分法的使用條件:

  1. 待查找的序列區間單調有序(單調遞增或單調遞減都可以)

  2. 待查找序列和題目的要求建立的函數關系單調有序

也就是說,在將區間一分為二後,答案只能出現在其中的一個區間,不能同時出現在兩個區間內,這樣的情形下才適合二分。如果不能保證這個條件,那就需要考慮別的方法。

二分法使用方法:

假設待查找序列和題目的要求之間的關系是單調遞增的,先取區間的中心,判斷該處函數值和題目標準值的大小關系,如果函數值偏小,那麽應該在中心右側的區間繼續查找;如果函數值偏大 ,那麽應該在中心左側區間繼續查找,直到找到對應的值或者區間縮小到左右端點之間不再包含其他數據結束。


二分的思想很重要,面對具體的情形需要做相應的變通。

二分法詳解