● 每週一言
越努力,越幸運。
導語
二分查找(binary search)可以說是最常見的算法思想之一了。即便是如此直觀簡單的算法,在不同場景下的實現方式也存在着微妙差別,稍有馬虎就需要打上冗餘難看的補丁來防止各種badcase。
趁着週末,小鬥帶着對binary search的濃厚興趣,在這裏作一下思考總結,並講講對補丁規避的理解。
binary search
二分查找的前提條件是待查找數據必須具備一定的有序關係,這個有序可以是升序、降序,或者某種擴展的順序關係。從二分查找算法執行的方式來看,不出以下三種情形:
情形a,二分不帶mid中間值。這種情形作爲二分查找最簡單的形式,一般只要求查找某一特定值的位置,且待查找序列中的元素不出現重複。比如在 [1, 3, 4, 6, 7, 9] 中查找4則返回下標2,查找5則返回-1。
情形b,二分左帶mid中間值。這種情形適用於查找相同元素的左邊界。比如在 [1, 3, 4, 4, 4, 5, 7, 9] 中查找4,返回的下標爲2。
情形c與情形b相反,爲二分右帶mid中間值。針對上述例子 [1, 3, 4, 4, 4, 5, 7, 9],同樣查找4,返回的下標則爲4。
在具體二分問題當中,有時並不想要精確匹配,而是想找最相近或是k個最相近的值。這時,在二分查找結束後就需要作進一步的算法處理。
此外,還存在不少二分查找的問題變種,其實都是萬變不離其宗,只要找準了兩個關鍵點便能迎刃而解。這兩個關鍵點分別爲:1. 確定有序序列是什麼;2. 確定mid比較方式。
所謂補丁,就是解決一些特殊情況或是邊界問題的代碼。比如,當待查找數據爲空數據時,是不需要執行算法的,如果不加處理,往往會報下標溢出之類的錯誤。
除開上述必要補丁,如果希望規避其他冗餘補丁,首先,需要考慮的是算法是否涵蓋除特殊情況以外的所有case;其次,算法如果已涵蓋所有case,是否能等同對待其中的邊界case。若不能做到上述兩點,冗餘補丁就不可避免了,代碼自然就會比較醜陋而不優雅。
比如,在上述二分算法中,如果處理的最小序列長度爲3,那麼長度爲0、1和2的序列就分別需要打補丁,這樣是不合理的。
以上便是二分查找與補丁規避,敬請期待下節內容。
結語
感謝各位的耐心閱讀,後續文章於每週日奉上,敬請期待。歡迎大家關注小鬥公衆號 對半獨白!